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. 二叉树的右视图【中等】
思路: BFS 层序遍历,每层只保留最后一个节点的值。
from collections import deque
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
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. 最长有效括号【困难】
思路: 栈存下标。初始化 -1 方便计算长度差。
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. 单词拆分【中等】
思路: DP。dp[i] 表示前 i 个字符能否被拆分。
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)
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
value = (x + y + carry) % 10
carry = (x + y + carry) // 10
ans = str(value) + ans
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 = {}
threshold = len(nums) // 2for num in nums:
count_dict[num] = count_dict.get(num, 0) + 1for k, v in count_dict.items():
if v > threshold:
return k
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. 两数之和【简单】
思路: Hash 表存储已遍历元素的索引,O(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
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]
15. 三数之和【中等】
思路: 排序 + 双指针。固定一个数,寻找另外两个数使和为 0。
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) + 1
rank_value = sorted(hash_table.items(), key=lambda x: x[1], reverse=True)
return [key for key, _ in rank_value[:k]]
287. 寻找重复数【中等】
思路: 哈希集检测重复。
classSolution:
deffindDuplicate(self, nums: List[int]) -> int:
hash_table = set()
for num in nums:
if num in hash_table:
return num
hash_table.add(num)
42. 接雨水【困难】
思路: 双指针维护左右最高水位。
classSolution:
deftrap(self, height: List[int]) -> int:
n = len(height)
max_left, max_right = 0, 0
left, right = 0, n - 1
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
cur_s = width * min(height[left], height[right])
ans = max(ans, cur_s)
if height[left] <= height[right]:
left += 1else:
right -= 1return ans
LCR 172. 统计目标成绩的出现次数【简单】
思路: 二分法找边界。
classSolution:
defcountTarget(self, scores: List[int], target: int) -> int:
defhelper(t):
left, right = 0, len(scores) - 1while left <= right:
mid = (left + right) // 2if scores[mid] < t:
left = mid + 1else:
right = mid - 1return left
l = helper(target)
r = helper(target + 1)
return r - l
34. 在排序数组中查找元素的第一个和最后一个位置【中等】
思路: 同上一题,二分查找左右边界。
classSolution:
defsearchRange(self, nums: List[int], target: int) -> List[int]:
ifnot nums:
return [-1, -1]
defhelper(t):
left, right = 0, len(nums) - 1while left <= right:
mid = (left + right) // 2if nums[mid] < t:
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
215. 数组中的第 K 个最大元素【中等】
思路: 快速选择算法(Quick Select)。
import random
classSolution:
deffindKthLargest(self, nums: List[int], k: int) -> int:
defquick_select(arr, k):
pivot = random.choice(arr)
big, equal, small = [], [], []
for x in arr:
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. 最小覆盖子串【困难】
思路: 滑动窗口 + 字符计数器。
from collections import Counter
classSolution:
defminWindow(self, s: str, t: str) -> str:
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. 无重复字符的最长子串【中等】
思路: 滑动窗口 + Set 去重。
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
排列
冒泡排序【排序模板】
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
快速排序【排序模板】
import random
classSolution:
defsortArray(self, nums: List[int]) -> List[int]:
defquicksort(arr, low, high):
if low < high:
pivot_idx = partition(arr, low, high)
quicksort(arr, low, pivot_idx - 1)
quicksort(arr, pivot_idx + 1, high)
return arr
defpartition(arr, low, high):
r = random.randint(low, high)
arr[r], arr[high] = arr[high], arr[r]
pivot = arr[high]
slow = fast = low
while fast <= high:
if arr[fast] < pivot:
arr[fast], arr[slow] = arr[slow], arr[fast]
slow += 1
fast += 1
arr[high], arr[slow] = arr[slow], arr[high]
return slow
n = len(nums)
return quicksort(nums, 0, n - 1)
283. 移动零【简单】
思路: 双指针保持非零元素相对顺序。
classSolution(object):
defmoveZeroes(self, nums):
left = 0for right inrange(len(nums)):
if nums[right] != 0:
nums[right], nums[left] = nums[left], nums[right]
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 = sorted(people, key=lambda x: (-x[0], x[1]))
ans = []
for person in people_sort:
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. 相交链表【简单】
思路: Hash 集存储一条链表的节点。
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:
slow = slow.next
tmp = tmp.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.next
cur.next = left if left else 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 or carry:
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.nextreturn ans.next
21. 合并两个有序链表【简单】
思路: 双指针合并。
classSolution:
defmergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
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.next
cur.next = list1 if list1 else 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.next
cur.next = l1 if l1 else l2
return dummy.next
n = len(lists)
if n == 0:
returnNoneif n == 1:
return lists[0]
left = self.mergeKLists(lists[:n // 2])
right = self.mergeKLists(lists[n // 2:])
return mergeTwoLists(left, right)
classSolution:
defcountBits(self, n: int) -> List[int]:
return [bin(i).count('1') for i inrange(n + 1)]
191. 位 1 的个数【简单】
思路: 逐位判断。
classSolution:
defhammingWeight(self, n: int) -> int:
bit_num = 32
one_bit = 0for i inrange(bit_num):
if n & (1 << i):
one_bit += 1return one_bit
231. 2 的幂【简单】
思路: 二进制只有一个 1。
classSolution:
defisPowerOfTwo(self, n: int) -> bool:
if n <= 0:
returnFalsereturn (n & (n - 1)) == 0
数组计算
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 = cur_min = ans = nums[0]
for i inrange(1, n):
temp_max = max(nums[i] * cur_min, nums[i] * cur_max, nums[i])
cur_min = min(nums[i] * cur_min, nums[i] * cur_max, nums[i])
cur_max = temp_max
ans = max(ans, cur_max)
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. 最长连续序列【中等】
思路: Hash 集 + 起点计数。
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 = s[i - 1]
right_new_char = 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]
from collections import deque
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 or c < 0or c >= cols or 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 的平方根【简单】
思路: 二分法或牛顿迭代。
import math
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
构造随机变量,等概率生成 1~n 的数
思路: 利用不等概率硬币构造等概率事件,再生成二进制位。
import math
defRand1(p=0.5):
return1if__import__('random').random() < p else0defRandN(n: int):
k = int(math.log2(n)) + 1whileTrue:
res = 0for _ inrange(k):
res = (res << 1) | Rand1()
if res <= n:
return res
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. 丑数【简单】
思路: 循环除 2、3、5。
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]