30 秒改错Q1 · 这段代码里埋了一个 Python 专属的坑——错在哪?
rows, cols = 3, 4
visited = [[False] * cols] * rows
visited[0][0] = True
看答案
翻车点①:[[False]*cols]*rows 复制的是引用。要 rows 份独立的行,只能用列表推导(见 C2)。
这一页做的是复健,不是学习:你会 Python,只是长期把写代码这件事委托给 AI 之后,手感萎缩了。所以本页的主体动作是打字,不是阅读——§2 的速查表是拿来查的,不是拿来读的;§3、§4 的练习篇幅是它的两倍,那才是重点。
先把范围划死,降低心理负担:LeetCode Python 是整个语言的一个极小子集。下面 24 条惯用法加 5 个专属翻车点,覆盖刷题日常会碰到的绝大部分写法——每一条都在构建时实际执行验证过,包括注释里的反例。碰到没收录的写法很正常,查一下就行,不必回头补课。
以下内容刷题用不到,一个都不用碰:
yield from、协程式用法)按使用频率排序。编号(C1、W1、Q5…)供 §3 的「复健自查」引用,点编号可跳回。
C1 a = [0] * n # 一维初始化:n 个 0
C2 g = [[0] * n for _ in range(m)] # 二维初始化;[[0]*n]*m 是 m 份同一引用(翻车点①)
C3 a[i:j], a[::-1] # 切片左闭右开;[::-1] 反转
C4 d[k] = d.get(k, 0) + 1 # dict 计数三连:键不存在按 0 算
C5 s.add(x); x in s # set:O(1) 判断存在性
C6 st.append(x); st.pop() # list 当栈:同侧进出,栈顶是 st[-1]
C7 max(best, x), min(xs), sum(xs) # 打擂台与聚合;max 还能带 key=
T1 for i, x in enumerate(nums): ... # 要下标也要值
T2 for a, b in zip(xs, ys): ... # 并排走两个序列,短的一停全停
T3 out = [f(x) for x in nums if ok(x)] # 推导式:过滤 + 变换一行完成
W1 s.lower(), c.isalnum() # 归一化 / 判断字母数字:125 靠这两个过滤
W2 ''.join(chs), s.split() # 拼接 / 按空白切分;字符串不可变,不能改单个字符
S1 nums.sort() # 原地升序;返回 None,别写 nums = nums.sort()
S2 pairs.sort(key=lambda p: (p[0], -p[1])) # 多关键字;数值键取负 = 这一键降序
Q1 from collections import deque, Counter, defaultdict
Q2 q = deque(); q.append(x); q.popleft() # BFS 队列:右进左出,两头都是 O(1)
Q3 Counter(s) # 一行频次统计,可当 dict 用
Q4 g = defaultdict(list); g[u].append(v) # 建图:首次访问自动变 []
Q5 heapq.heappush(h, x); heapq.heappop(h) # 最小堆;要最大堆就 push -x,3.14 起另有 heappush_max(翻车点④)
L1 best = float('inf') # 打擂台初始值;负无穷 float('-inf')
L2 7 // 2, -7 // 2 # 整除向下取整:结果是 3 和 -4(不是 -3),DP 边界常见坑
L3 a, b = b, a + b # 平行赋值:右边整体先求值;链表反转 / 滚动 DP 靠它
L4 class ListNode: ... # 题目自带的定义,会读会用即可,不用自己写
L5 import sys; sys.setrecursionlimit(10 ** 6) # 深递归保险(树 / 图 DFS 防爆栈)
g[0][0] 等于改每一行——正确写法见 C2 的列表推导。
P1 g = [[0] * n] * m # m 行是同一个 list 的 m 个引用memo=None,函数体里再建。
P2 def f(x, memo={}): memo[x] = 1; return len(memo)UnboundLocalError。在 inner 开头加 nonlocal cnt。
P3 def outer():
cnt = 0
def inner():
cnt += 1 # 少了 nonlocal cnt
inner()heappop 永远弹最小。要最大堆:push 时存 -x,pop 后取负还原(见 Q5);Python 3.14 起也可用 heappush_max / heappop_max,先确认面试环境的版本。
P4 largest = heapq.heappop(h) # 想要最大值?弹出来的偏偏是最小值i += 1。++i 是两个一元正号,静默等于 i,连报错都不给。
P5 i++ # SyntaxError;更阴险的是 ++i 合法但什么都不做规则,一条都别放水:
10 道复健题,每道标注它复健的惯用法。它们同时全部收录在正文各章(其中 9 道是热身层)——双重用途:打完这一页,全书 17 道热身题你已经完成了 53%。
10 道全部一次提交通过(或第二次),且没有一道超过 15 分钟 → 关闭本页,进入正文。达不到就重打不达标的那几道——不加新题。
给你一段带 bug 的代码,30 秒内指出错在哪。五段代码分别踩了 §2 的五个翻车点。
30 秒改错Q1 · 这段代码里埋了一个 Python 专属的坑——错在哪?
rows, cols = 3, 4
visited = [[False] * cols] * rows
visited[0][0] = True
翻车点①:[[False]*cols]*rows 复制的是引用。要 rows 份独立的行,只能用列表推导(见 C2)。
30 秒改错Q2 · 这段代码里埋了一个 Python 专属的坑——错在哪?
def collect(node, acc=[]):
acc.append(node)
return acc
翻车点②:可变默认参数跨调用共享。习惯写法 acc=None,函数体里 if acc is None: acc = []。
30 秒改错Q3 · 这段代码里埋了一个 Python 专属的坑——错在哪?
def count_leaves(root):
total = 0
def dfs(node):
if node is None:
return
if not node.left and not node.right:
total += 1
dfs(node.left)
dfs(node.right)
dfs(root)
return total
翻车点③:total += 1 让 Python 把 total 当 dfs 的本地变量。在 dfs 开头加 nonlocal total,或改成 dfs 返回计数再相加。
30 秒改错Q4 · 这段代码里埋了一个 Python 专属的坑——错在哪?
import heapq
def top3(nums):
h = list(nums)
heapq.heapify(h)
return [heapq.heappop(h) for _ in range(3)] # 想拿最大的 3 个
翻车点④:heappop 弹的是最小值。push 时取负、pop 后还原,或者直接 heapq.nlargest(3, nums)(3.14 起也可用 heappush_max 等,先确认环境版本)。
30 秒改错Q5 · 这段代码里埋了一个 Python 专属的坑——错在哪?
def total(nums):
s, i = 0, 0
while i < len(nums):
s += nums[i]
i++
return s
翻车点⑤:i++ 连运行的机会都没有——编译期就 SyntaxError。更阴险的是前缀 ++i 合法但什么都不做。
5 道改错题与 §2 的 5 个翻车点一一对应;每段代码的 bug 都在构建时实际执行证明过是真的。选项顺序构建时打乱,别背位置。