MarkDown 「靡不有初,鲜克有终」 2020-04-21T05:17:04.000Z http://blog.tunpok.com/ Ching Hexo leetcode-number-of-islands http://blog.tunpok.com/2020/04/21/leetcode-number-of-islands/ 2020-04-21T04:55:17.000Z 2020-04-21T05:17:04.000Z 200. 岛屿数量

题目

这种矩阵题现在第一反应就是用广度优先搜索做,类似之前算和0之间的距离那题。遍历矩阵,遇到 1 就将 1 改成 0,然后广度优先搜索找出 1 相邻的所有 1,这就是一个岛屿,以此类推。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import collections
class Solution:
def numIslands(self, grid) -> int:
rows = len(grid)
if not rows:
return 0
cols = len(grid[0])
islands = 0
for r in range(rows):
for l in range(cols):
if grid[r][l] == '1':
islands += 1
grid[r][l] = '0'
neighbors = collections.deque([(r, l)])
while neighbors:
x, y = neighbors.popleft()
for x_, y_ in [[x-1, y], [x+1, y], [x, y-1], [x, y+1]]:
if 0<=x_<rows and 0<=y_<cols and grid[x_][y_] == '1':
neighbors.append([x_, y_])
grid[x_][y_] = '0'
return islands
]]>
<h3 id="200-岛屿数量"><a href="#200-岛屿数量" class="headerlink" title="200. 岛屿数量"></a>200. 岛屿数量</h3><p><a href="https://leetcode-cn.com/problems/number-of-islands/">题目</a></p>
leetcode-string-to-integer-atoi http://blog.tunpok.com/2020/04/16/leetcode-string-to-integer-atoi/ 2020-04-16T11:50:10.000Z 2020-04-16T11:56:40.000Z 8. 字符串转换整数 (atoi)

题目

没什么好说的,注意各种情况,识别到数字之后就一直要是数字。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Solution:
def myAtoi(self, str: str) -> int:
p = ''
str = str.lstrip()
n = ''
min_int = -2**31
max_int = 2**31-1
isnumeric = False
for x in str:
if not isnumeric and x == '-':
p = '-'
isnumeric = True
continue
if not isnumeric and x == '+':
isnumeric = True
continue
if x.isnumeric():
n += x
isnumeric = True
else:
break
if not n:
return 0
if int(n) > max_int:
if p:
return min_int
else:
return max_int
p += n
return int(p)
# 32 ms13.6 MB
]]>
<h3 id="8-字符串转换整数-atoi"><a href="#8-字符串转换整数-atoi" class="headerlink" title="8. 字符串转换整数 (atoi)"></a>8. 字符串转换整数 (atoi)</h3><p><a href="https://leetcode-cn.com/problems/string-to-integer-atoi/">题目</a></p>
leetcode-merge-intervals http://blog.tunpok.com/2020/04/16/leetcode-merge-intervals/ 2020-04-16T11:22:26.000Z 2020-04-16T11:22:48.000Z 56. 合并区间

题目

首先将区间按起点由小到大排序,这样相邻的两个就能通过终点判断是否重合。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution:
def merge(self, intervals):
if not intervals:
return []
intervals.sort()
merged = []
l = len(intervals)
m = intervals[0]
for x in range(l-1):
j = intervals[x+1]
if m[1] >= j[0]:
if m[1] <= j[1]:
m = [m[0], j[1]]
else:
continue
else:
merged.append(m)
m = j
if m:
merged.append(m)
return merged
]]>
<h3 id="56-合并区间"><a href="#56-合并区间" class="headerlink" title="56. 合并区间"></a>56. 合并区间</h3><p><a href="https://leetcode-cn.com/problems/merge-intervals/">题目</a></p>
leetcode-01-matrix http://blog.tunpok.com/2020/04/16/leetcode-01-matrix/ 2020-04-16T04:26:34.000Z 2020-04-16T04:26:56.000Z 542. 01 矩阵

题目

想了两种思路

  1. 0 位置的上下左右是 1, 上下左右中有跟 1 相邻的就是 2,以此类推,从 0 的坐标开始往上下左右四个方向扩散。如果我们把同意个距离的看作是一层,可以用一个队列依次存放每一层的坐标,直至每个坐标都被计算过。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    class Solution:
    def updateMatrix(self, matrix: List[List[int]]) -> List[List[int]]:
    m, n = len(matrix), len(matrix[0])
    dist = [[0] * n for _ in range(m)]
    zeroes_pos = [(i, j) for i in range(m) for j in range(n) if matrix[i][j] == 0]
    # 将所有的 0 添加进初始队列中
    q = collections.deque(zeroes_pos)
    seen = set(zeroes_pos)

    # 广度优先搜索
    while q:
    i, j = q.popleft()
    for ni, nj in [(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)]:
    if 0 <= ni < m and 0 <= nj < n and (ni, nj) not in seen:
    dist[ni][nj] = dist[i][j] + 1
    q.append((ni, nj))
    seen.add((ni, nj))

    return dist
  2. 从左上角开往右下角遍历矩阵,当前坐标的距离由左和上两个位置的值确定。遍历一遍后,再反过来从右下角开始往左上角遍历,当前坐标的距离根据右和下两个位置的值确定,比较这两次得出的值中较小的一个即为该点的距离。

]]>
<h3 id="542-01-矩阵"><a href="#542-01-矩阵" class="headerlink" title="542. 01 矩阵"></a>542. 01 矩阵</h3><p><a href="https://leetcode-cn.com/problems/01-matrix/">题目</a></p>
leetcode-add-two-numbers-ii http://blog.tunpok.com/2020/04/14/leetcode-add-two-numbers-ii/ 2020-04-14T15:22:39.000Z 2020-04-14T15:28:35.000Z 445. 两数相加 II

题目

看到顺序的链表就想到用倒序链表的方法做,折腾了半天

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
class ListNode:
def __init__(self, x):
self.val = x
self.next = None

class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
def _reverse(l):
if l.next:
last = _reverse(l.next)
l.next.next = l
l.next = None
return last
return l

l1e = _reverse(l1)
l2e = _reverse(l2)
new_l = ListNode(0)
head = new_l
c = 0
import ipdb; ipdb.set_trace()
while l1e and l2e:
new_val = l1e.val + l2e.val
if c==1:
new_val += 1
c = 0
if new_val >= 10:
new_val -= 10
c = 1

new_l.val = new_val
next_n = None
if l1e.next and l2e.next or c:
next_n = ListNode(c)
new_l.next = next_n
new_l = next_n
l1e = l1e.next
l2e = l2e.next
if l2e:
l1e = l2e
if not l1e and c:
l1e = ListNode(0)
while l1e:
new_l.val = l1e.val
new_l.val += c
c = 0
if new_l.val >= 10:
c = 1
new_l.val -= 10
l1e = l1e.next
if l1e:
new_l.next = ListNode(0)
new_l = new_l.next
else:
new_l.next = ListNode(1)

return _reverse(head)

# 84 ms13.9 MB

最后面各种进位的处理应该还可以更清晰优雅一些,但是懒得搞了,感觉很蠢。翻了答案看到了小 tips,需要倒序处理的情况可以用栈。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
s1, s2 = [], []
while l1:
s1.append(l1.val)
l1 = l1.next
while l2:
s2.append(l2.val)
l2 = l2.next
ans = None
carry = 0
while s1 or s2 or carry != 0:
a = 0 if not s1 else s1.pop()
b = 0 if not s2 else s2.pop()
cur = a + b + carry
carry = cur // 10
cur %= 10
curnode = ListNode(cur)
curnode.next = ans
ans = curnode
return ans

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/add-two-numbers-ii/solution/liang-shu-xiang-jia-ii-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

不过就执行效率来看差不多。

]]>
<h3 id="445-两数相加-II"><a href="#445-两数相加-II" class="headerlink" title="445. 两数相加 II"></a>445. 两数相加 II</h3><p><a href="https://leetcode-cn.com/problems/add-two-numbers-ii/">题目</a></p>
leetcode-design-twitter http://blog.tunpok.com/2020/04/14/leetcode-design-twitter/ 2020-04-14T08:11:41.000Z 2020-04-14T15:29:34.000Z 355. 设计推特

题目

做出来倒是很简单,由于没有并发和特别的条件,测试数据量也不大。一开始搞错了,以为传入的 twitterId 就是自增的 id,结果其实是每条推的内容,所以增加了一个计数器去标记 id。

主要的考点应该是 多路归并 这个东西。我用的是排序,在数据量大的时候应该会有些问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
class Twitter:

def __init__(self):
"""
Initialize your data structure here.
"""
self.tweets = {}
self.followers = {}
self._tid = 0


def postTweet(self, userId: int, tweetId: int) -> None:
"""
Compose a new tweet.
"""
if not self.tweets.get(userId):
self.tweets[userId] = []
self.tweets[userId].append((self._tid, tweetId))
self._tid += 1


def getNewsFeed(self, userId: int) :
"""
Retrieve the 10 most recent tweet ids in the user's news feed. Each item in the news feed must be posted by users who the user followed or by the user herself. Tweets must be ordered from most recent to least recent.
"""
foers = self.followers.get(userId, set())
foers = foers.union((userId,))
tweets = []
for fo in foers:
tweets.extend(self.tweets.get(fo, [])[-10:])
return [tw[1] for tw in sorted(tweets, reverse=True)[:10]]


def follow(self, followerId: int, followeeId: int) -> None:
"""
Follower follows a followee. If the operation is invalid, it should be a no-op.
"""
if not self.followers.get(followerId):
self.followers[followerId] = set()
self.followers[followerId].add(followeeId)


def unfollow(self, followerId: int, followeeId: int) -> None:
"""
Follower unfollows a followee. If the operation is invalid, it should be a no-op.
"""
if not self.followers.get(followerId):
self.followers[followerId] = set()
if followeeId in self.followers[followerId]:
self.followers[followerId].remove(followeeId)

#100 ms19.2 MB

# Your Twitter object will be instantiated and called as such:
# obj = Twitter()
# obj.postTweet(userId,tweetId)
# param_2 = obj.getNewsFeed(userId)
# obj.follow(followerId,followeeId)
# obj.unfollow(followerId,followeeId)
]]>
<h3 id="355-设计推特"><a href="#355-设计推特" class="headerlink" title="355. 设计推特"></a>355. 设计推特</h3><p><a href="https://leetcode-cn.com/problems/design-twitter/">题目</a></p>
leetcode-he-wei-sde-lian-xu-zheng-shu-xu-lie-lcof http://blog.tunpok.com/2020/04/09/leetcode-he-wei-sde-lian-xu-zheng-shu-xu-lie-lcof/ 2020-04-09T14:14:56.000Z 2020-04-14T15:29:40.000Z 面试题57 - II. 和为s的连续正数序列

题目

又是小学奥数。由等差数列求和公式$\cfrac{(首项 + 末项)×项数}{2}$ 可知,当首项为 1 的时候项数最多,又由于是连续正整数,$n^2 < (1+n)×n < (n+1)^2 $,那最大的 $n$ 就不大于 $\sqrt{2×target} + 1$。

由小到大遍历 $n$,可以求得首项。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import math
class Solution:
def findContinuousSequence(self, target: int):
n = int(math.sqrt(2 * target) + 1)
if n < 2:
return []
sum_list = []
a = 0
for i in range(2, n+1):
a = ((2 * target) / i + 1 - i) / 2
if a and not a % 1:
a = int(a)
s_ = []
for j in range(0, i):
s_.append(a + j)
sum_list.append(s_)
return sorted(sum_list)
# 60 ms13.7 MB
]]>
<h3 id="面试题57-II-和为s的连续正数序列"><a href="#面试题57-II-和为s的连续正数序列" class="headerlink" title="面试题57 - II. 和为s的连续正数序列"></a>面试题57 - II. 和为s的连续正数序列</h3><p><a href="https://leetcode-cn.com/problems/he-wei-sde-lian-xu-zheng-shu-xu-lie-lcof/">题目</a></p>
leetcode-the-masseuse-lcci http://blog.tunpok.com/2020/04/09/leetcode-the-masseuse-lcci/ 2020-04-08T16:35:26.000Z 2020-04-08T17:14:04.000Z 面试题 17.16. 按摩师

题目

一开始以为是用递归,想了半天没想出来,偷看了一下答案。答案的思路跟递归类似,假设在当前 $i$ 时刻,$dp[i][0]$ 为当前预约不接的情况下最长预约时间,$dp[i][1]$ 则为接受当前预约的最长预约时间。

那很显然,由于不能接受相邻两个预约,$dp[i][1] = dp[i-1][0] + nums_i$

不接受当前预约的话,上一个预约接不接受都可以,$dp[i][0] = max(dp[i-1][0], dp[i-1][1])$

最后只要比较两种情况即可 $max(dp[i][0], dp[i][1])$

1
2
3
4
5
6
7
8
9
10
11
class Solution:
def massage(self, nums) -> int:
if not nums:
return 0
n = len(nums)
not_choose = 0
choose = 0
for n in nums:
not_choose, choose = max(not_choose, choose), not_choose+n
return max(not_choose, choose)
# 52 ms13.6 MB

这种问题原来有个名字叫动态规划,上面推导的方程叫状态转移方程,可以找找资料来看一下。

]]>
<h3 id="面试题-17-16-按摩师"><a href="#面试题-17-16-按摩师" class="headerlink" title="面试题 17.16. 按摩师"></a>面试题 17.16. 按摩师</h3><p><a href="https://leetcode-cn.com/problems/the-masseuse-lcci/">题目</a></p>
leetcode-compress-string-lcci http://blog.tunpok.com/2020/04/01/leetcode-compress-string-lcci/ 2020-04-01T07:51:22.000Z 2020-04-01T07:57:26.000Z 面试题 01.06. 字符串压缩

题目

遍历一遍字符串,遇到跟上一个字符不同的字符时记录上一个字符的重复长度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution:
def compressString(self, S: str) -> str:
if not S:
return S
c = ''
prev = S[0]
p_len = 1
for w in S[1:]:
if w != prev:
c += '%s%s' % (prev, p_len)
prev = w
p_len = 1
else:
p_len += 1
c += '%s%s' % (prev, p_len)
if len(S) > len(c):
return c
return S
# 52 ms13.8 MB
]]>
<h3 id="面试题-01-06-字符串压缩"><a href="#面试题-01-06-字符串压缩" class="headerlink" title="面试题 01.06. 字符串压缩"></a>面试题 01.06. 字符串压缩</h3><p><a href="https://leetcode-cn.com/problems/compress-string-lcci/">题目</a></p>
leetcode-1103 http://blog.tunpok.com/2020/04/01/leetcode-1103/ 2020-04-01T03:22:20.000Z 2020-04-08T17:17:27.000Z 1103. 分糖果 II

题目

小学奥数题。主要思路就是等差数列求和 $\cfrac{(首项 + 末项)×项数}{2}$ 。可以用公式把每一个位置获得的总糖果数表示出来。我的方法稍微蠢了点,算了每一轮的总糖果数,其实可以直接求总共发了多少次糖果,除以每轮的人数就可以得出发了多少轮。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Solution:
def distributeCandies(self, candies: int, num_people: int):
total = 0
i = 0
# import ipdb; ipdb.set_trace()
while total <= candies:
t = (num_people*i)*num_people + int((1+num_people)*num_people/2)
if total + t <= candies:
total += t
i += 1
else:
break
remaining = candies - total
print(total, remaining, i)
l = []
for n in range(1, num_people+1):
if not total:
current_candy = n
else:
current_candy = n+i*num_people

n_count = int((0+(i-1))*(i)/2)
print(current_candy, n_count)
if remaining >= current_candy:
l.append(n_count*num_people + n*i + current_candy)
remaining -= current_candy
else:
l.append(n_count*num_people + n*i + remaining)
remaining = 0
return l
# 28 ms13.7 MB,
]]>
<h3 id="1103-分糖果-II"><a href="#1103-分糖果-II" class="headerlink" title="1103. 分糖果 II"></a>1103. 分糖果 II</h3><p><a href="https://leetcode-cn.com/problems/distribute-candies-to-people/">题目</a></p>
leetcode-1160 http://blog.tunpok.com/2020/04/01/leetcode-1160/ 2020-03-31T16:18:48.000Z 2020-04-01T07:57:06.000Z 1160. 拼写单词

题目

利用列表 remove 方法,检查 chars 中是否有足够的字母拼写 word

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution:
def countCharacters(self, words, chars: str) -> int:

words_ = ''
for w in words:
lchars = list(chars)
try:
for l in w:
lchars.remove(l)
except:
continue
words_ += w

return len(words_)
# 152 ms14.1 MB
]]>
<h3 id="1160-拼写单词"><a href="#1160-拼写单词" class="headerlink" title="1160. 拼写单词"></a>1160. 拼写单词</h3><p><a href="https://leetcode-cn.com/problems/find-words-that-can-be-formed-by-characters/">题目</a></p>
leetcode-1071 http://blog.tunpok.com/2020/03/30/leetcode-1071/ 2020-03-30T14:03:01.000Z 2020-03-30T14:04:17.000Z 1071. 字符串的最大公因子

题目

如果存在这样字符串,那它最大的长度就是这两个字符串长度的最大公约数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Solution:
def gcdOfStrings(self, str1: str, str2: str) -> str:
if str1[0] != str2[0]:
return ''

a = len(str1)
b = len(str2)
print(a, b)
if a < b:
str1, str2 = str2, str1
a = len(str1)
b = len(str2)

if not a%b:
for x in range(0, a//b):
if str1[x*b:(x+1)*b] != str2:
return ''
return str2
else:
for x in range(b, 0, -1):
print(x)
if x==b or b%x or a%x:
continue
for y in range(0, b//x):
if str2[y*x:(y+1)*x] != str2[b-x:b]:
return ''
for y in range(0, a//x):
if str1[y*x:(y+1)*x] != str2[0:x]:
return ''
return str2[0:x]
# 44 ms13.9 MB

官方解答中还给了一种巧妙的解法,如果 str1 + str2 == str2 + str1 的话,可以证明必定存在这样一个字符串,其长度为两个字符串长度的最大公约数。

]]>
<h3 id="1071-字符串的最大公因子"><a href="#1071-字符串的最大公因子" class="headerlink" title="1071. 字符串的最大公因子"></a>1071. 字符串的最大公因子</h3><p><a href="https://leetcode-cn.com/problems/greatest-common-divisor-of-strings/">题目</a></p>
leetcode-999 http://blog.tunpok.com/2020/03/30/leetcode-999/ 2020-03-30T13:03:25.000Z 2020-03-30T13:03:41.000Z 999. 可以被一步捕获的棋子数

题目

遍历一遍找到车的坐标,然后按上下左右四个方向循环一下看碰到的第一个棋子是什么。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class Solution:
def numRookCaptures(self, board) -> int:
i = j = 0
for row in board:
if 'R' in row:
break
i += 1
j = row.index('R')
count = 0
# right
for x in range(j + 1, 8):
if row[x] == 'p':
count += 1
break
if row[x] == 'B':
break
# left
for x in range(j, 0, -1):
if row[x] == 'p':
count += 1
break
if row[x] == 'B':
break
# up
for x in range(i, 0, -1):
if board[x][j] == 'p':
count += 1
break
if board[x][j] == 'B':
break
# down
for x in range(i+1, 8):
if board[x][j] == 'p':
count += 1
break
if board[x][j] == 'B':
break

return count

#36 ms13.6 MB

问题不难,官方解答中给了一个方向数组的概念,上下左右是 (0, 1) (0, -1) (-1, 0) (1, 0),有点像向量的意思。走的路线等于方向数组乘以步数。

]]>
<h3 id="999-可以被一步捕获的棋子数"><a href="#999-可以被一步捕获的棋子数" class="headerlink" title="999. 可以被一步捕获的棋子数"></a>999. 可以被一步捕获的棋子数</h3><p><a href="https://leetcode-cn.com/problems/available-captures-for-rook/">题目</a></p>
leetcode-914 http://blog.tunpok.com/2020/03/29/leetcode-914/ 2020-03-29T14:41:09.000Z 2020-03-29T14:52:07.000Z 914. 卡牌分组

题目

将大牌堆分成多个牌数量相等的小牌堆,就是求每张牌数量的公约数。先遍历一遍得到每张牌的数量,然后找出比2大的公约数即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution:
def hasGroupsSizeX(self, deck) -> bool:
dc = {}
max_d = 0
for d in deck:
if d not in dc:
dc[d] = 0
dc[d] += 1
if max_d < d:
max_d = d
if max_d < dc[d]:
max_d = dc[d]
has_x = True
if max_d == 1:
max_d = 2

for i in range(2, max_d + 1):
has_x = True
for k,v in dc.items():
if v % i:
has_x = False
break
if has_x and i >= 2:
return True
return False

#56 ms13.8 MB
]]>
<h3 id="914-卡牌分组"><a href="#914-卡牌分组" class="headerlink" title="914. 卡牌分组"></a>914. 卡牌分组</h3><p><a href="https://leetcode-cn.com/problems/x-of-a-kind-in-a-deck-of-cards/">题目</a></p>
leetcode-1013 http://blog.tunpok.com/2020/03/29/leetcode-1013/ 2020-03-29T13:09:22.000Z 2020-03-29T13:15:11.000Z 1013. 将数组分成和相等的三个部分

题目

因为是整数数组,如果能均分成三份,则数组和肯定是3的倍数。然后遍历数组逐端求和使得和为 sum(A)/3。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution:
def canThreePartsEqualSum(self, A) -> bool:
if not A:
return False
sa = sum(A)
if sa % 3:
return False
s = sa // 3
s1 = 0
s2 = 0


for i in range(len(A)):
s1 += A[i]
if s1 == s and (i+1) < len(A):
for j in range(len(A[i+1:])):
s2 += A[i+1+j]
if s2 == s and j+1 < len(A[i+1:]) and sum(A[i+j+2:])== s:
return True
return False
#60 ms18.7 MB
]]>
<h3 id="1013-将数组分成和相等的三个部分"><a href="#1013-将数组分成和相等的三个部分" class="headerlink" title="1013. 将数组分成和相等的三个部分"></a>1013. 将数组分成和相等的三个部分</h3><p><a href="https://leetcode-cn.com/problems/partition-array-into-three-parts-with-equal-sum/">题目</a></p>
leetcode-876 http://blog.tunpok.com/2020/03/26/leetcode-876/ 2020-03-26T13:18:41.000Z 2020-03-26T13:19:10.000Z 876. 链表的中间结点

题目

思路是遍历一遍得到整个链表,讲每个 node 放进一个 list,就可以通过下标得到中间的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Definition for singly-linked list.
class ListNode:
def __init__(self, x):
self.val = x
self.next = None

class Solution:
def middleNode(self, head: ListNode) -> ListNode:
l = []
n = head
while n.next:
l.append(n)
n = n.next
l.append(n)
return l[len(l)//2]

#44 ms13.7 MB

看官方解答,还有一个骚操作,通过两个速度不一样的指针,一个一次走一步,一个两次走一步,快的走到底时,慢的就在中间了。

1
2
3
4
5
6
7
8
9
10
11
12
class Solution:
def middleNode(self, head: ListNode) -> ListNode:
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
return slow

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/middle-of-the-linked-list/solution/lian-biao-de-zhong-jian-jie-dian-by-leetcode-solut/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
]]>
<h3 id="876-链表的中间结点"><a href="#876-链表的中间结点" class="headerlink" title="876. 链表的中间结点"></a>876. 链表的中间结点</h3><p><a href="https://leetcode-cn.com/problems/middle-of-the-linked-list/">题目</a></p>
leetcode-836 http://blog.tunpok.com/2020/03/25/leetcode-836/ 2020-03-25T14:41:25.000Z 2020-03-25T14:41:44.000Z 836. 矩形重叠

题目

看两个矩形有没有重叠,就看两个矩形在坐标轴上的投影有没有重叠。

1
2
3
4
5
6
7
8
9
class Solution:
def isRectangleOverlap(self, rec1, rec2) -> bool:
return ((min(rec1[2], rec2[2]) > max(rec1[0], rec2[0]))
and (min(rec1[3], rec2[3]) > max(rec1[1], rec2[1])))

s = Solution()
s.isRectangleOverlap(rec1 = [0,0,2,2], rec2 = [1,1,3,3])

#40 ms13.7 MB
]]>
<h3 id="836-矩形重叠"><a href="#836-矩形重叠" class="headerlink" title="836. 矩形重叠"></a>836. 矩形重叠</h3><p><a href="https://leetcode-cn.com/problems/rectangle-overlap/">题目</a></p>
leetcode-409 http://blog.tunpok.com/2020/03/25/leetcode-409/ 2020-03-25T13:55:38.000Z 2020-03-25T13:55:54.000Z 409. 最长回文串

题目

一开始理解错题目了,以为是寻找字符串中的最长回文串,结果是构造。但是原理基本一样,由于回文中心对称,所以是由多个偶数个相同字母和至多一个奇数个相同字母组成。

这样只要数给出的字符串中有几个偶数个相同字母和几个奇数个相同字母就可以了。奇数个相同字母可以减少一个当偶数个用,最后再加回去一个。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution:
def longestPalindrome(self, s: str) -> int:
d = {}
for l in s:
if not l in d:
d[l] = 0
d[l] += 1

i = 0
odd = False
for k, v in d.items():
if v % 2:
i += (v-1)
odd = True
else:
i += v
if odd:
i += 1
return i

#40 ms13.6 MB
]]>
<h3 id="409-最长回文串"><a href="#409-最长回文串" class="headerlink" title="409. 最长回文串"></a>409. 最长回文串</h3><p><a href="https://leetcode-cn.com/problems/longest-palindrome/">题目</a></p>
leetcode-543 http://blog.tunpok.com/2020/03/25/leetcode-543/ 2020-03-25T11:13:52.000Z 2020-04-14T15:29:53.000Z 543. 二叉树的直径

题目

这题做出来了但是没有通过运行时间的测试,主要还是没想明白二叉树的直径到底是什么东西,用了个蠢办法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# Definition for a binary tree node.
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None

class Solution:
def diameterOfBinaryTree(self, root: TreeNode) -> int:
if not root:
return 0
last_node = -1
routes = []
start = root
node_stack = [root]
while (start.left or start.right or node_stack):
if start != node_stack[-1]:
node_stack.append(start)

if last_node == start.right:
node_stack = node_stack[:-1]
if not node_stack:
break
last_node = start
start = node_stack[-1]
continue

if start.left and last_node != start.left:
start = start.left
last_node = start
continue

if start.right:
start = start.right
last_node = start
continue

routes.append(node_stack)
node_stack = node_stack[:-1]
if not node_stack:
break
last_node = start
start = node_stack[-1]

max_l = 0
for route in routes:
for route_ in routes:
intersection = 0
if route != route_:
intersection = len(set(route).intersection(set(route_)))
if intersection:
intersection -= 1
max_l = max(max_l, len(set(route)| set(route_)) - intersection)
return max_l - 1

L43 之前做的是以深度优先的方式遍历一遍树,得出每个点的路径。后面的是将所有路径组合在一起得出任意两个点间的路径,算出最大长度。

其实以某个点为根节点的树的直径,就是某个节点的左子树的深度和右子树的深度的和,用递归来处理这个会比较容易理解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution(object):
def diameterOfBinaryTree(self, root):
self.ans = 1
def depth(node):
# 访问到空节点了,返回0
if not node: return 0
# 左儿子为根的子树的深度
L = depth(node.left)
# 右儿子为根的子树的深度
R = depth(node.right)
# 计算d_node即L+R+1 并更新ans
self.ans = max(self.ans, L+R+1)
# 返回该节点为根的子树的深度
return max(L, R) + 1

depth(root)
return self.ans - 1

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/diameter-of-binary-tree/solution/er-cha-shu-de-zhi-jing-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
]]>
<h3 id="543-二叉树的直径"><a href="#543-二叉树的直径" class="headerlink" title="543. 二叉树的直径"></a>543. 二叉树的直径</h3><p><a href="https://leetcode-cn.com/problems/diameter-of-binary-tree/">题目</a></p>
leetcode-225 http://blog.tunpok.com/2020/03/23/leetcode-225/ 2020-03-23T15:35:05.000Z 2020-03-23T15:35:24.000Z 225. 用队列实现栈

题目

注意栈是 FILO(First In Last Out),Python 的 list 是 FIFO(First In First Out)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class MyStack:

def __init__(self):
"""
Initialize your data structure here.
"""
self.data = []


def push(self, x: int) -> None:
"""
Push element x onto stack.
"""
self.data.append(x)
return


def pop(self) -> int:
"""
Removes the element on top of the stack and returns that element.
"""
return self.data.pop(-1)


def top(self) -> int:
"""
Get the top element.
"""
return self.data[-1]


def empty(self) -> bool:
"""
Returns whether the stack is empty.
"""
return not bool(self.data)



# Your MyStack object will be instantiated and called as such:
# obj = MyStack()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.top()
# param_4 = obj.empty()

#24 ms13.5 MB
]]>
<h3 id="225-用队列实现栈"><a href="#225-用队列实现栈" class="headerlink" title="225. 用队列实现栈"></a>225. 用队列实现栈</h3><p><a href="https://leetcode-cn.com/problems/implement-stack-using-queues/">题目</a></p>