classSolution:
defisSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:
if p isNoneor q isNone:
return p isNoneand q isNonereturn p.val == q.val andself.isSameTree(p.left, q.left) andself.isSameTree(p.right, q.right)
101. 对称二叉树【简单】
递归比较镜像对称的左右子树。
classSolution:
defisSymmetric(self, root: Optional[TreeNode]) -> bool:
defhelper(p, q):
ifnot p ornot q:
returnnot p andnot q
return p.val == q.val and helper(p.left, q.right) and helper(p.right, q.left)
return helper(root.left, root.right)
199. 二叉树的右视图【中等】
广度优先搜索,取每层最右侧节点。
classSolution:
defrightSideView(self, root: Optional[TreeNode]) -> List[int]:
ifnot root:
return []
queue = deque([root])
ans = []
while queue:
n = len(queue)
ans.append(queue[-1].val)
for _ inrange(n):
node = queue.popleft()
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return ans
103. 二叉树的锯齿形层序遍历【中等】
层序遍历基础上增加层索引控制方向。
classSolution:
defzigzagLevelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
ifnot root:
return []
queue = [root]
ans = []
layer_idx = 0while queue:
n = len(queue)
cur_level = []
for _ inrange(n):
node = queue.pop(0)
cur_level.append(node.val)
if layer_idx % 2 == 1:
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
else:
if node.right:
queue.append(node.right)
if node.left:
queue.append(node.left)
ans.append(cur_level)
layer_idx += 1return ans
124. 二叉树中的最大路径和【困难】
递归计算以当前节点为起点的最大路径,同时更新全局最大值。
classSolution:
def__init__(self):
self.ans = -float('inf')
defmaxPathSum(self, root: Optional[TreeNode]) -> int:
defdfs(node):
ifnot node:
return0
left = max(dfs(node.left), 0)
right = max(dfs(node.right), 0)
cur_sum = node.val + left + right
self.ans = max(self.ans, cur_sum)
return node.val + max(left, right)
dfs(root)
returnself.ans
108. 将有序数组转换为二叉搜索树【简单】
递归选取中间元素作为根节点。
classSolution:
defsortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]:
ifnot nums:
returnNone
n = len(nums) // 2
left = self.sortedArrayToBST(nums[:n])
right = self.sortedArrayToBST(nums[n+1:])
return TreeNode(nums[n], left, right)
字符串
20. 有效的括号【简单】
栈匹配,注意空栈判断语法。
classSolution(object):
defisValid(self, s):
iflen(s) % 2 == 1:
returnFalse
pairs_dict = {')': '(', '}': '{', ']': '['}
stack = []
for c in s:
if c in pairs_dict:
ifnot stack or stack[-1] != pairs_dict[c]:
returnFalse
stack.pop()
else:
stack.append(c)
returnnot stack
32. 最长有效括号【困难】
栈存下标,计算长度差。
classSolution(object):
deflongestValidParentheses(self, s):
stack = [-1]
ans = 0for i inrange(len(s)):
if s[i] == '(':
stack.append(i)
else:
stack.pop()
if stack:
ans = max(ans, i - stack[-1])
else:
stack.append(i)
return ans
647. 回文子串【中等】
中心扩展法,分奇偶长度处理。
classSolution(object):
defcountSubstrings(self, s):
n = len(s)
defsolve(left, right):
cnt = 0while0 <= left < n and0 <= right < n and s[left] == s[right]:
cnt += 1
left -= 1
right += 1return cnt
ans = 0for i inrange(n):
ans += solve(i, i)
ans += solve(i, i + 1)
return ans
139. 单词拆分【中等】
动态规划,判断前缀是否可拆且后缀在字典中。
classSolution:
defwordBreak(self, s: str, wordDict: List[str]) -> bool:
n = len(s)
dp = [True] + [False] * n
for i inrange(n):
for j inrange(i + 1, n + 1):
if dp[i] and s[i:j] in wordDict:
dp[j] = Truereturn dp[-1]
394. 字符串解码【中等】
双栈或单栈提取字母与数字。
classSolution:
defdecodeString(self, s: str) -> str:
stack = []
for c in s:
if c != ']':
stack.append(c)
else:
chars = ''while stack and stack[-1] != '[':
chars = stack[-1] + chars
stack.pop()
stack.pop() # pop '['
num = ''while stack and stack[-1].isdigit():
num = stack[-1] + num
stack.pop()
stack.append(int(num) * chars)
return''.join(stack)
72. 编辑距离【中等】
经典 DP,考虑增删改三种操作。
classSolution:
defminDistance(self, word1: str, word2: str) -> int:
m, n = len(word1), len(word2)
dp = [[0] * (n + 1) for _ inrange(m + 1)]
for i inrange(m + 1): dp[i][0] = i
for i inrange(n + 1): dp[0][i] = i
for i inrange(1, m + 1):
for j inrange(1, n + 1):
if word1[i - 1] == word2[j - 1]:
dp[i][j] = dp[i - 1][j - 1]
else:
dp[i][j] = min(dp[i][j - 1], dp[i - 1][j], dp[i - 1][j - 1]) + 1return dp[m][n]
classSolution:
defaddStrings(self, num1: str, num2: str) -> str:
ans = ""
carry = 0
i, j = len(num1) - 1, len(num2) - 1while i >= 0or j >= 0or carry:
x = int(num1[i]) if i >= 0else0
y = int(num2[j]) if j >= 0else0
s = x + y + carry
ans = str(s % 10) + ans
carry = s // 10
i -= 1
j -= 1return ans
搜索查找
448. 找到所有数组中消失的数字【简单】
辅助标记数组记录存在性。
classSolution:
deffindDisappearedNumbers(self, nums: List[int]) -> List[int]:
n = len(nums)
flag = [0] * (n + 1)
for x in nums:
flag[x] = 1return [i for i inrange(1, n + 1) if flag[i] == 0]
classSolution:
defmaxProfit(self, prices: List[int]) -> int:
ans = 0for i inrange(1, len(prices)):
ans += max(prices[i] - prices[i - 1], 0)
return ans
169. 多数元素【简单】
哈希统计数量。
classSolution:
defmajorityElement(self, nums: List[int]) -> int:
count_dict = {}
for num in nums:
count_dict[num] = count_dict.get(num, 0) + 1returnmax(count_dict, key=count_dict.get)
739. 每日温度【中等】
单调栈,从右向左或从左向右均可。
classSolution:
defdailyTemperatures(self, temperatures: List[int]) -> List[int]:
n = len(temperatures)
ans = [0] * n
stack = []
for i inrange(n):
while stack and temperatures[i] > temperatures[stack[-1]]:
j = stack.pop()
ans[j] = i - j
stack.append(i)
return ans
1. 两数之和【简单】
哈希表存储已遍历元素及其索引。
classSolution:
deftwoSum(self, nums: List[int], target: int) -> List[int]:
hash_table = {}
for i, num inenumerate(nums):
diff = target - num
if diff in hash_table:
return [hash_table[diff], i]
hash_table[num] = i
return []
167. 两数之和 II - 输入有序数组【中等】
双指针相向移动。
classSolution:
deftwoSum(self, numbers: List[int], target: int) -> List[int]:
left, right = 0, len(numbers) - 1while left < right:
s = numbers[left] + numbers[right]
if s < target:
left += 1elif s > target:
right -= 1else:
return [left + 1, right + 1]
return []
15. 三数之和【中等】
排序后固定一个元素,双指针找另外两个。
classSolution:
defthreeSum(self, nums: List[int]) -> List[List[int]]:
nums.sort()
ans = []
n = len(nums)
for i inrange(n - 2):
if i > 0and nums[i] == nums[i - 1]:
continue
left, right = i + 1, n - 1while left < right:
s = nums[i] + nums[left] + nums[right]
if s < 0:
left += 1elif s > 0:
right -= 1else:
ans.append([nums[i], nums[left], nums[right]])
while left < right and nums[left] == nums[left + 1]:
left += 1while left < right and nums[right] == nums[right - 1]:
right -= 1
left += 1
right -= 1return ans
classSolution:
deftopKFrequent(self, nums: List[int], k: int) -> List[int]:
hash_table = {}
for num in nums:
hash_table[num] = hash_table.get(num, 0) + 1returnsorted(hash_table, key=lambda x: hash_table[x], reverse=True)[:k]
287. 寻找重复数【中等】
哈希集检测重复。
classSolution:
deffindDuplicate(self, nums: List[int]) -> int:
seen = set()
for num in nums:
if num in seen:
return num
seen.add(num)
return -1
42. 接雨水【困难】
双指针维护左右最高点。
classSolution:
deftrap(self, height: List[int]) -> int:
left, right = 0, len(height) - 1
max_left, max_right = 0, 0
ans = 0while left < right:
max_left = max(max_left, height[left])
max_right = max(max_right, height[right])
if max_left < max_right:
ans += max_left - height[left]
left += 1else:
ans += max_right - height[right]
right -= 1return ans
11. 盛最多水的容器【中等】
双指针向中间收缩。
classSolution:
defmaxArea(self, height: List[int]) -> int:
left, right = 0, len(height) - 1
ans = 0while left < right:
width = right - left
h = min(height[left], height[right])
ans = max(ans, width * h)
if height[left] < height[right]:
left += 1else:
right -= 1return ans
LCR 172. 统计目标成绩的出现次数【简单】
二分法搜索边界。
classSolution:
defcountTarget(self, scores: List[int], target: int) -> int:
defhelper(target_val):
left, right = 0, len(scores) - 1while left <= right:
mid = (left + right) // 2if scores[mid] < target_val:
left = mid + 1else:
right = mid - 1return left
return helper(target + 1) - helper(target)
34. 在排序数组中查找元素的第一个和最后一个位置【中等】
同上一题,二分查找边界。
classSolution:
defsearchRange(self, nums: List[int], target: int) -> List[int]:
defhelper(target_val):
left, right = 0, len(nums) - 1while left <= right:
mid = (left + right) // 2if nums[mid] < target_val:
left = mid + 1else:
right = mid - 1return left
l = helper(target)
r = helper(target + 1)
if r > l:
return [l, r - 1]
return [-1, -1]
1287. 有序数组中出现次数超过 25% 的元素【简单】
哈希计数。
classSolution:
deffindSpecialInteger(self, arr: List[int]) -> int:
n = len(arr)
thre = int(n * 0.25)
hash_table = {}
for a in arr:
hash_table[a] = hash_table.get(a, 0) + 1if hash_table[a] > thre:
return a
return arr[0]
215. 数组中的第 K 个最大元素【中等】
快速选择算法思想。
classSolution:
deffindKthLargest(self, nums: List[int], k: int) -> int:
import random
defquick_select(nums, k):
pivot = random.choice(nums)
big, equal, small = [], [], []
for x in nums:
if x > pivot: big.append(x)
elif x < pivot: small.append(x)
else: equal.append(x)
iflen(big) >= k:
return quick_select(big, k)
iflen(big) + len(equal) < k:
return quick_select(small, k - len(big) - len(equal))
return pivot
return quick_select(nums, k)
209. 长度最小的子数组【中等】
滑动窗口,枚举右端点收缩左端点。
classSolution:
defminSubArrayLen(self, target: int, nums: List[int]) -> int:
n = len(nums)
ans = n + 1
s = 0
left = 0for right, x inenumerate(nums):
s += x
while s >= target:
ans = min(ans, right - left + 1)
s -= nums[left]
left += 1return ans if ans <= n else0
76. 最小覆盖子串【困难】
滑动窗口配合字符计数器。
classSolution:
defminWindow(self, s: str, t: str) -> str:
from collections import Counter
cnt_win = Counter()
cnt_t = Counter(t)
ans_left, ans_right = -float('inf'), float('inf')
left = 0for right, x inenumerate(s):
cnt_win[x] += 1while cnt_win >= cnt_t:
if right - left < ans_right - ans_left:
ans_left, ans_right = left, right
cnt_win[s[left]] -= 1
left += 1return s[ans_left:ans_right + 1] if ans_left >= 0else""
3. 无重复字符的最长子串【中等】
滑动窗口维护不重复集合。
classSolution:
deflengthOfLongestSubstring(self, s: str) -> int:
n = len(s)
ans = 0
visited = set()
left = 0for right, x inenumerate(s):
while x in visited:
visited.remove(s[left])
left += 1
visited.add(x)
ans = max(ans, right - left + 1)
return ans
排列
冒泡排序【排序模板】
O(n^2) 基础排序。
classSolution(object):
defsortArray(self, nums):
n = len(nums)
for i inrange(1, n):
for j inrange(0, n - i):
if nums[j] > nums[j + 1]:
nums[j], nums[j + 1] = nums[j + 1], nums[j]
return nums
classSolution(object):
defmoveZeroes(self, nums):
left = 0for right inrange(len(nums)):
if nums[right] != 0:
nums[left], nums[right] = nums[right], nums[left]
left += 1return nums
75. 颜色分类【中等】
三指针分区。
classSolution:
defsortColors(self, nums: List[int]) -> None:
n = len(nums)
p0, p2 = 0, n - 1
i = 0while i <= p2:
if nums[i] == 2:
nums[i], nums[p2] = nums[p2], nums[i]
p2 -= 1elif nums[i] == 0:
nums[i], nums[p0] = nums[p0], nums[i]
p0 += 1
i += 1else:
i += 1
406. 根据身高重建队列【中等】
先按身高降序、k 升序排序,再插入。
classSolution:
defreconstructQueue(self, people: List[List[int]]) -> List[List[int]]:
people.sort(key=lambda x: (-x[0], x[1]))
ans = []
for person in people:
ans.insert(person[1], person)
return ans
977. 有序数组的平方【简单】
双指针从两端向中间比较平方值。
classSolution:
defsortedSquares(self, nums: List[int]) -> List[int]:
n = len(nums)
left, right = 0, n - 1
ans = []
while left <= right:
if nums[left]**2 <= nums[right]**2:
ans.append(nums[right]**2)
right -= 1else:
ans.append(nums[left]**2)
left += 1return ans[::-1]
31. 下一个排列【中等】
从右向左找第一个较小元素,交换后反转右侧。
classSolution:
defnextPermutation(self, nums: List[int]) -> None:
n = len(nums)
i = n - 2while i >= 0and nums[i] >= nums[i + 1]:
i -= 1if i >= 0:
j = n - 1while nums[j] <= nums[i]:
j -= 1
nums[i], nums[j] = nums[j], nums[i]
left, right = i + 1, n - 1while left < right:
nums[left], nums[right] = nums[right], nums[left]
left += 1
right -= 1
组合
49. 字母异位词分组【中等】
排序后作为 Key 分组。
classSolution(object):
defgroupAnagrams(self, strs):
d = {}
for s in strs:
sorted_s = ''.join(sorted(s))
d[sorted_s] = d.get(sorted_s, []) + [s]
returnlist(d.values())
78. 子集【中等】
迭代构建子集。
classSolution(object):
defsubsets(self, nums):
ans = [[]]
for num in nums:
tmp = []
for i in ans:
tmp.append([num] + i)
ans += tmp
return ans
46. 全排列【中等】
回溯法交换元素。
classSolution:
defpermute(self, nums: List[int]) -> List[List[int]]:
n = len(nums)
ans = []
defdfs(start):
if start == n:
ans.append(nums[:])
returnfor i inrange(start, n):
nums[i], nums[start] = nums[start], nums[i]
dfs(start + 1)
nums[i], nums[start] = nums[start], nums[i]
dfs(0)
return ans
47. 全排列 II【中等】
回溯法加剪枝去重。
classSolution:
defpermuteUnique(self, nums: List[int]) -> List[List[int]]:
n = len(nums)
ans = []
defdfs(start):
if start == n:
ans.append(nums[:])
return
dic = set()
for i inrange(start, n):
if nums[i] in dic:
continue
dic.add(nums[i])
nums[i], nums[start] = nums[start], nums[i]
dfs(start + 1)
nums[i], nums[start] = nums[start], nums[i]
dfs(0)
return ans
LCR 157. 套餐内商品的排列顺序【中等】
字符串转列表回溯。
classSolution:
defgoodsOrder(self, goods: str) -> List[str]:
n = len(goods)
lst = list(goods)
ans = []
defdfs(start):
if start == n:
ans.append(''.join(lst))
returnfor i inrange(start, n):
lst[i], lst[start] = lst[start], lst[i]
dfs(start + 1)
lst[i], lst[start] = lst[start], lst[i]
dfs(0)
returnlist(set(ans))
classSolution(object):
defisPalindrome(self, head):
l = []
while head:
l.append(head.val)
head = head.nextreturn l == l[::-1]
160. 相交链表【简单】
哈希存储一条链表的节点。
classSolution:
defgetIntersectionNode(self, headA: ListNode, headB: ListNode) -> Optional[ListNode]:
ifnot headA ornot headB:
returnNone
link_set = set()
cur = headA
while cur:
link_set.add(cur)
cur = cur.next
cur = headB
while cur:
if cur in link_set:
return cur
cur = cur.nextreturnNone
141. 环形链表【简单】
快慢指针追及问题。
classSolution:
defhasCycle(self, head: Optional[ListNode]) -> bool:
ifnot head:
returnFalse
slow, fast = head, head
while fast and fast.next:
slow = slow.next
fast = fast.next.nextif slow == fast:
returnTruereturnFalse
142. 环形链表 II【中等】
快慢指针相遇后重置一指针找入口。
classSolution:
defdetectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
ifnot head:
returnNone
slow, fast = head, head
while fast and fast.next:
slow = slow.next
fast = fast.next.nextif slow == fast:
breakelse:
returnNone
tmp = head
while tmp != slow:
tmp = tmp.next
slow = slow.nextreturn slow
148. 排序链表【中等】
归并排序。
classSolution:
defsortList(self, head: Optional[ListNode]) -> Optional[ListNode]:
ifnot head ornot head.next:
return head
slow, fast = head, head.nextwhile fast and fast.next:
slow = slow.next
fast = fast.next.next
mid = slow.next
slow.next = None
left = self.sortList(head)
right = self.sortList(mid)
ans = ListNode()
cur = ans
while left and right:
if left.val < right.val:
cur.next = left
left = left.nextelse:
cur.next = right
right = right.next
cur = cur.nextif left:
cur.next = left
elif right:
cur.next = right
return ans.next
classSolution:
defremoveNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
dummy = ListNode(next=head)
right = dummy
for _ inrange(n):
right = right.next
left = dummy
while right.next:
left = left.next
right = right.next
left.next = left.next.nextreturn dummy.next
83. 删除排序链表中的重复元素【简单】
跳过相同值节点。
classSolution:
defdeleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]:
ifnot head:
returnNone
cur = head
while cur.next:
if cur.next.val == cur.val:
cur.next = cur.next.nextelse:
cur = cur.nextreturn head
82. 删除排序链表中的重复元素 II【中等】
哨兵节点处理头节点删除。
classSolution:
defdeleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]:
dummy = ListNode(next=head)
cur = dummy
while cur.nextand cur.next.next:
if cur.next.next.val == cur.next.val:
val = cur.next.val
while cur.nextand cur.next.val == val:
cur.next = cur.next.nextelse:
cur = cur.nextreturn dummy.next
203. 移除链表元素【简单】
哨兵节点迭代判断。
classSolution:
defremoveElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]:
ifnot head:
returnNone
dummy = ListNode(next=head)
cur = dummy
while cur and cur.next:
if cur.next.val == val:
cur.next = cur.next.nextelse:
cur = cur.nextreturn dummy.next
2. 两数相加【中等】
参照字符串加法模板。
classSolution:
defaddTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
ans = ListNode(0)
cur = ans
carry = 0while l1 or l2:
x = l1.val if l1 else0
y = l2.val if l2 else0
s = x + y + carry
cur.next = ListNode(s % 10)
cur = cur.next
carry = s // 10if l1: l1 = l1.nextif l2: l2 = l2.nextif carry:
cur.next = ListNode(carry)
return ans.next
21. 合并两个有序链表【简单】
双指针取小值。
classSolution:
defmergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
ifnot list1 andnot list2:
returnNone
ans = ListNode()
cur = ans
while list1 and list2:
if list1.val < list2.val:
cur.next = list1
list1 = list1.nextelse:
cur.next = list2
list2 = list2.next
cur = cur.nextif list1:
cur.next = list1
elif list2:
cur.next = list2
return ans.next
23. 合并 K 个升序链表【困难】
分治两两合并。
classSolution:
defmergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
defmergeTwoLists(l1, l2):
dummy = ListNode()
cur = dummy
while l1 and l2:
if l1.val < l2.val:
cur.next = l1
l1 = l1.nextelse:
cur.next = l2
l2 = l2.next
cur = cur.nextif l1: cur.next = l1
elif l2: cur.next = l2
return dummy.nextifnot lists:
returnNoneiflen(lists) == 1:
return lists[0]
mid = len(lists) // 2
left = self.mergeKLists(lists[:mid])
right = self.mergeKLists(lists[mid:])
return mergeTwoLists(left, right)
位运算
461. 汉明距离【简单】
异或后统计 1 的个数。
classSolution:
defhammingDistance(self, x: int, y: int) -> int:
xor = x ^ y
dist = 0for i inrange(32):
if (xor >> i) & 1:
dist += 1return dist
338. 比特位计数【简单】
转二进制计数。
classSolution(object):
defcountBits(self, n):
ans = []
for i inrange(n + 1):
ans.append(bin(i).count('1'))
return ans
191. 位 1 的个数【简单】
逐位判断。
classSolution:
defhammingWeight(self, n: int) -> int:
one_bit = 0for i inrange(32):
if n & (1 << i):
one_bit += 1return one_bit
231. 2 的幂【简单】
判断二进制中 1 的个数。
classSolution:
defisPowerOfTwo(self, n: int) -> bool:
if n <= 0:
returnFalsereturnbin(n).count('1') == 1
数组计算
238. 除自身以外数组的乘积【中等】
前缀乘积与后缀乘积。
classSolution:
defproductExceptSelf(self, nums: List[int]) -> List[int]:
n = len(nums)
front_mul = [1] * n
behind_mul = [1] * n
for i inrange(1, n):
front_mul[i] = front_mul[i - 1] * nums[i - 1]
for i inrange(n - 2, -1, -1):
behind_mul[i] = behind_mul[i + 1] * nums[i + 1]
return [front_mul[i] * behind_mul[i] for i inrange(n)]
152. 乘积最大子数组【中等】
同时维护最大和最小乘积。
classSolution:
defmaxProduct(self, nums: List[int]) -> int:
n = len(nums)
if n == 1:
return nums[0]
cur_max = [0] * n
cur_min = [0] * n
ans = nums[0]
cur_max[0], cur_min[0] = nums[0], nums[0]
for i inrange(1, n):
cur_max[i] = max(nums[i] * cur_min[i - 1], nums[i] * cur_max[i - 1], nums[i])
cur_min[i] = min(nums[i] * cur_min[i - 1], nums[i] * cur_max[i - 1], nums[i])
ans = max(ans, cur_max[i])
return ans
53. 最大子数组和【中等】
经典 DP 模板。
classSolution:
defmaxSubArray(self, nums: List[int]) -> int:
n = len(nums)
if n == 1:
return nums[0]
dp = [0] * n
dp[0] = nums[0]
for i inrange(1, n):
dp[i] = max(nums[i], dp[i - 1] + nums[i])
returnmax(dp)
300. 最长递增子序列【中等】
DP 状态转移。
classSolution:
deflengthOfLIS(self, nums: List[int]) -> int:
n = len(nums)
if n == 1:
return1
dp = [1] * n
for i inrange(n):
for j inrange(i):
if nums[i] > nums[j]:
dp[i] = max(dp[i], dp[j] + 1)
returnmax(dp)
128. 最长连续序列【中等】
哈希集合查找连续序列。
classSolution:
deflongestConsecutive(self, nums: List[int]) -> int:
hash_set = set(nums)
ans = 0for num in hash_set:
if num - 1notin hash_set:
length_from_here = 1
cur_num = num
while cur_num + 1in hash_set:
cur_num += 1
length_from_here += 1
ans = max(ans, length_from_here)
return ans
438. 找到字符串中所有字母异位词【中等】
滑动窗口字符统计。
classSolution:
deffindAnagrams(self, s: str, p: str) -> List[int]:
window_size = len(p)
n = len(s)
ans = []
window_cnt = [0] * 26
p_cnt = [0] * 26for c in p:
p_cnt[ord(c) - ord('a')] += 1for c in s[:window_size]:
window_cnt[ord(c) - ord('a')] += 1if p_cnt == window_cnt:
ans.append(0)
for i inrange(1, n - window_size + 1):
left_del_char, right_new_char = s[i - 1], s[i + window_size - 1]
window_cnt[ord(left_del_char) - ord('a')] -= 1
window_cnt[ord(right_new_char) - ord('a')] += 1if p_cnt == window_cnt:
ans.append(i)
return ans
989. 数组形式的整数加法【简单】
逐位计算模板。
classSolution:
defaddToArrayForm(self, num: List[int], k: int) -> List[int]:
n = len(num)
i = n - 1
carry = 0
ans = []
while i >= 0or k != 0:
x = num[i] if i >= 0else0
y = k % 10if k != 0else0
s = x + y + carry
ans.append(s % 10)
carry = s // 10
i -= 1
k //= 10if carry:
ans.append(carry)
return ans[::-1]
119. 杨辉三角 II【简单】
递推每行值。
classSolution:
defgetRow(self, rowIndex: int) -> List[int]:
row_num = rowIndex + 1
T = [[1] * (i + 1) for i inrange(row_num)]
for i inrange(row_num):
for j inrange(1, i):
T[i][j] = T[i - 1][j - 1] + T[i - 1][j]
return T[rowIndex]
198. 打家劫舍【中等】
DP 状态转移。
classSolution:
defrob(self, nums: List[int]) -> int:
n = len(nums)
if n == 1:
return nums[0]
if n == 2:
returnmax(nums[0], nums[1])
dp = [0] * n
dp[0] = nums[0]
dp[1] = max(nums[0], nums[1])
for i inrange(2, n):
dp[i] = max(dp[i - 1], dp[i - 2] + nums[i])
return dp[-1]
213. 打家劫舍 II【中等】
分情况讨论首尾不可同时偷。
classSolution:
defrob(self, nums: List[int]) -> int:
n = len(nums)
if n == 1:
return nums[0]
if n == 2:
returnmax(nums[0], nums[1])
dp1 = [0] * n
dp1[0] = nums[0]
dp1[1] = max(nums[0], nums[1])
for i inrange(2, n - 1):
dp1[i] = max(dp1[i - 1], dp1[i - 2] + nums[i])
ans1 = dp1[-2]
dp2 = [0] * n
dp2[1] = nums[1]
dp2[2] = max(nums[1], nums[2])
for i inrange(3, n):
dp2[i] = max(dp2[i - 1], dp2[i - 2] + nums[i])
ans2 = dp2[-1]
returnmax(ans1, ans2)
classSolution:
defmaxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
n = len(nums)
ans = []
q = deque()
for i, x inenumerate(nums):
while q and x >= nums[q[-1]]:
q.pop()
q.append(i)
if i - q[0] >= k:
q.popleft()
if i >= k - 1:
ans.append(nums[q[0]])
return ans
56. 合并区间【中等】
排序后合并重叠区间。
classSolution:
defmerge(self, intervals: List[List[int]]) -> List[List[int]]:
intervals.sort(key=lambda p: p[0])
ans = []
for p in intervals:
if ans and p[0] <= ans[-1][1]:
ans[-1][1] = max(p[1], ans[-1][1])
else:
ans.append(p)
return ans
classSolution:
defnumIslands(self, grid: List[List[str]]) -> int:
defdfs(grid, r, c):
rows, cols = len(grid), len(grid[0])
if r < 0or r > rows - 1or c < 0or c > cols - 1or grid[r][c] != '1':
return
grid[r][c] = '2'
dfs(grid, r + 1, c)
dfs(grid, r - 1, c)
dfs(grid, r, c + 1)
dfs(grid, r, c - 1)
rows, cols = len(grid), len(grid[0])
ans = 0for r inrange(rows):
for c inrange(cols):
if grid[r][c] == '1':
dfs(grid, r, c)
ans += 1return ans
classSolution:
defsetZeroes(self, matrix: List[List[int]]) -> None:
rows, cols = len(matrix), len(matrix[0])
row_flag, col_flag = [0] * rows, [0] * cols
for r inrange(rows):
for c inrange(cols):
if matrix[r][c] == 0:
row_flag[r] = 1
col_flag[c] = 1for r inrange(rows):
for c inrange(cols):
if row_flag[r] or col_flag[c]:
matrix[r][c] = 0
48. 旋转图像【中等】
水平翻转 + 主对角线翻转。
classSolution:
defrotate(self, matrix: List[List[int]]) -> None:
n = len(matrix)
for i inrange(n // 2):
for j inrange(n):
matrix[i][j], matrix[n - i - 1][j] = matrix[n - i - 1][j], matrix[i][j]
for i inrange(n):
for j inrange(i):
matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]
867. 转置矩阵【简单】
行列交换。
classSolution:
deftranspose(self, matrix: List[List[int]]) -> List[List[int]]:
rows, cols = len(matrix), len(matrix[0])
ans = [[0] * rows for _ inrange(cols)]
for i inrange(rows):
for j inrange(cols):
ans[j][i] = matrix[i][j]
return ans
数学计算
69. x 的平方根【简单】
二分法或牛顿迭代。
classSolution:
defmySqrt(self, x: int) -> int:
if x == 0:
return0
left, right = 1, x
ans = 1while left <= right:
mid = (left + right) // 2if mid * mid <= x:
ans = mid
left = mid + 1else:
right = mid - 1return ans
343. 整数拆分【中等】
DP 分解乘积。
classSolution:
defintegerBreak(self, n: int) -> int:
if n == 1:
return1
dp = [0] * (n + 1)
dp[1] = 1for i inrange(2, n + 1):
for j inrange(1, i):
dp[i] = max(dp[i], j * (i - j), j * dp[i - j])
return dp[n]
263. 丑数【简单】
循环除因子。
classSolution:
defisUgly(self, n: int) -> bool:
if n <= 0:
returnFalsefor p in [2, 3, 5]:
while n % p == 0:
n //= p
return n == 1
classSolution:
defaddDigits(self, num: int) -> int:
if num == 0:
return0return (num - 1) % 9 + 1
202. 快乐数【简单】
哈希检测环或快慢指针。
classSolution:
defisHappy(self, n: int) -> bool:
defcompute_next(n):
total = 0while n > 0:
digit = n % 10
total += digit ** 2
n //= 10return total
slow, fast = n, compute_next(n)
whileTrue:
if slow == fast:
returnFalseif fast == 1:
returnTrue
slow = compute_next(slow)
fast = compute_next(compute_next(fast))
图
207. 课程表【中等】
DFS 判断是否有环。
classSolution:
defcanFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
graph = [[] for _ inrange(numCourses)]
for a, b in prerequisites:
graph[b].append(a)
states = [0] * numCourses
defdfs(x):
states[x] = 1for node in graph[x]:
if states[node] == 1or (states[node] == 0and dfs(node)):
returnTrue
states[x] = 2returnFalsefor i inrange(numCourses):
if states[i] == 0and dfs(i):
returnFalsereturnTrue
64. 最小路径和【中等】
DP 累加最小路径。
classSolution:
defminPathSum(self, grid: List[List[int]]) -> int:
rows, cols = len(grid), len(grid[0])
dp = [[0] * cols for _ inrange(rows)]
dp[0][0] = grid[0][0]
for i inrange(1, rows):
dp[i][0] = dp[i - 1][0] + grid[i][0]
for j inrange(1, cols):
dp[0][j] = dp[0][j - 1] + grid[0][j]
for i inrange(1, rows):
for j inrange(1, cols):
dp[i][j] = min(dp[i][j - 1], dp[i - 1][j]) + grid[i][j]
return dp[rows - 1][cols - 1]