跳转至

刷题进度

144 题进度清单,与 刷题方案 一一对应(一阶段 94 题 + 二阶段 50 道新题)。 复习/二刷清单(双指针 7、复习 43、Hard 二刷 3)与一阶段题目重复,按章节勾选即可,不重复列。 本文件在 git 中跟踪,并由 MkDocs 从 content/ 构建进站点。

进度速览

  • 一阶段 94 题完成
  • 二阶段 50 道新题完成
  • 全量二刷通过(43 + 50 = 93 题筛一遍)

一、第一阶段:筑基速通(94 题)

数组:三个最基础的模板(4)

链表:dummy 头节点解决一切边界问题(6)

哈希表:把暴力的第二层循环换成查表(6)

字符串:只保留两道,KMP 不用手撕(2)

栈与队列:模板短,性价比最高的一章(6)

二叉树:全场最大的一章,砍掉 BST 增删改(16)

回溯:一个模板通吃十道题(10)

贪心:全书最该砍的一章(9)

动态规划:唯一要刷到 3/4 的一章(26)

单调栈:三道题够了(3)

图论:只保留 DFS 灌水和拓扑排序(6)

二、第二阶段:Hot100 验收(50 道新题)

新题 47 道

哈希 / 数组 / 技巧(10):

双指针 / 滑动窗口(5):

矩阵(4):

二分查找(5):

链表(7):

栈与堆(3):

二叉树(6):

图论 / 字典树(2):

回溯(2):

动态规划(3):

Hard 新增(3)

三、错题本

按 刷题方案 的「错题本怎么记(一行就够)」:

  • 一刷收口:LC 题号 题名 | 套路 | 卡点:一句话
  • 二刷 60 秒说不出思路的题记 ★,进入三刷
  • 三刷只看错题本
题号 套路 卡点 状态
LC 977 有序数组的平方 对撞指针 题设说“返回新数组”却硬要原地改(nums 既读又写,left 钉死 0 不移动),46% 随机用例挂;标准解是新数组从后往前填、源只读 2026-09-02 已 AC 137/137
LC 322 零钱兑换 完全背包 遍历顺序搞反了,求组合数要"先物品后容量"
LC 142 环形链表II 快慢指针 ① 相遇点≠环入口,缺第二阶段(ptr=head 与 slow 同速走);② 判相遇用值比较 slow.val==fast.val 不可靠,必须引用相等 2026-10-28 已 AC 18/18
LC 160 相交链表 双指针换轨 换轨时 if(pA==null) pA=headB; 后又无条件 pA=pA.next;,跳过了对方头节点;换轨那一步不能再 next,须用 else 分支 2026-10-28 已 AC 41/41
LC 15 三数之和 排序+对撞指针 只写了内层去重❷❸,漏了外层❶ i>0 && nums[i]==nums[i-1] continue,同一固定值重复枚举 → 重复三元组([-1,0,1] 收两次);剪枝用 >0 不是 >=0(否则丢 [0,0,0]) 2026-10-28 已 AC 316/316
LC 18 四数之和 排序+双层+对撞 ① j 去重条件写成 j>0(应为 j>i+1),相邻同值时第一个 j 被跳过 → [0,0,0,0] 返回空;② long sum = a+b+c+d 仍 int 溢出(表达式内先按 int 算),须 (long) a + b + c + d 2026-10-28 已 AC 295/295
LC 239 滑动窗口最大值 单调队列 ① 出结果时用 pollFirst()(弹出)而非 peekFirst()(只读)→ 最大值被弹走,示例1 输出 [3,-1,5,3,6,7];② 弹队尾用 <= 不是 <(相等时候选留新不留旧) 2026-10-28 已 AC 53/53
LC 347 前 K 个高频元素 小顶堆 TopK swap 写成 heap[j] = heap[i](复制而非交换,原 heap[j] 丢失)→ 结果值重复 [1,1]/[4,4,4];正确三步 t=heap[i]; heap[i]=heap[j]; heap[j]=t 2026-10-28 已 AC 26/26
LC 111 二叉树的最小深度 BFS 层序 ① count++ 放进 for 内层 → 变成"节点计数"而非"层号";且叶子处只 break 不 return,while 继续跑导致返回值错乱。层号必须每层 +1,找叶子要 return ② offer(pop.left) 没判 null → ArrayDeque 拒绝 null 直接 NPE 2026-10-30 已 AC 53/53
LC 98 验证二叉搜索树 BST 中序 / 上下界 中序版连踩:① 末行写成 root.left(右子树没查);② 漏 prev = root.val(检查永远失效);③ > 漏等号;④ 方向写成 prev < root.val(②和④互相掩盖,看着全对其实全错);⑤ prev 当 Integer 参数传 → 子层更新传不回父层([5,6,null]、[1,1] 误判 true) 2026-10-30 已 AC 86/86(两版)
LC 538 BST 转累加树 反中序 分离版里内部递归调了入口方法 convertBST(而非 cBST)→ 入口的 sum = 0 每层执行,累加全被清零,输出与输入完全相同 2026-10-30 已 AC 215/215(两版)
LC 108 有序数组转 BST 二分递归建树 三坑连锁导致 StackOverflow:① 终止条件写 left == right(应 left > right)② mid 写成 left + (right + left) / 2(应 right - left)③ 子树区间忘了排除 mid(build(left, mid)/build(mid, right))。口诀:mid 是根,左 mid-1 右 mid+1 2026-10-31 已 AC 31/31
LC 216 组合总和III 回溯+剪枝 出口条件写成一行 path.size()==k && remain==0:remain 不为 0 时不 return、继续进 for,need=0 把候选上限撑到 10+,往 path 里塞 10/11 幽灵值——结果虽对但 k=2,n=45 递归 3203 次对比分开写 45 次(71 倍)。改成:外层 if 管"停"、内层 if 管"收"、return 无条件 2026-11-03 已 AC 19/19
LC 746 最小花费爬楼梯 DP(虚拟层/流派) v1 返回 dp[n-1]:楼顶是【虚拟层】不是数组末位——收顶可从 last 跳1 或 从 last-1 跳2 且都免费 → min(dp[n-1], dp[n-2])。到达付/离开付两种流派都行但收账格子错位一档,选定流派后"初始化/循环上限/返回值"全套按流派一致 2026-11-07 已 AC 286/286
LC 435 无重叠区间 区间贪心 v1 WA 10/60:① 无排序([5,6] 先在场全堵死)② 判定 cur[1]!=start——相接/有间隙都误判(应 start >= keepEnd 保留、< 才删)③ 删除后 cur=intervals[i] 跟随被删者——参照必须恒为 keptEnd。v2:keep 只加不清 + del=n-keep 补集 2026-11-06 已 AC 60/60
LC 47 全排列 II 回溯(去重/撤销粒度) v1 两坑:① used = new boolean[](掀桌重开)——把"分支结束时的全 F 终态"用在分支进行中的每一步,祖先的 true 被撕 → 跨层连用锁死失效,[1,1,1]/[1,2,2] 幻影(撤销粒度=选择粒度,只撤自己那一笔"used[i]=false";与 90 漏撤销互为镜像:撤太少/撤太多);② 去重判 i > 1,第一对相邻同值(i=1 对 i=0)漏网 → i > 0。start 在排列里只当层号计时器,管挡人的是 used 2026-11-04 已 AC 33/33
LC 46 全排列 回溯(排列/值身份vs下标身份) used 用 HashSet 装【值】:46 题设互异碰巧可用,重复值输入会归零([1,1,2] 收 0 个——第一个 1 进 Set 后第二个 1 永远被拦,path 凑不满)。used 的身份必须是下标(boolean[]),值只是下标的影子;另学交换法:path=数组前缀、池=[start..]、撤销=同对 swap 再来一遍、收账必须拷快照 2026-11-04 已 AC 26/26(交换法)
LC 90 子集 II 回溯(撤销/收账/止损三分) ① 漏了撤销行 path.remove(size-1):单链树([1,1])碰巧全对,真分叉树([1,2,2])立刻脏——兄弟分支踩脏 path → 缺 [2]/[2,2]、多幻影 [1,2,2,2]/[1,2,2,2,2](去重墙挡不住跨分支传染);② 概念澄清:收账无条件在第一行(答案=每个节点),break 是剪枝(传染至层尾),continue 只死单支 2026-11-04 已 AC 21/21
LC 77 组合 回溯模板 ① start=0 起点写错(候选应为 [1,n]),数量对但值全偏 1(C(4,2)=6 个 [0..3] 组合),范围检查才抓到;② JDK17 无 List.removeLast()(JDK21+ 才有),命令行编译失败,需 remove(path.size()-1);③ 剪枝闭边界用 < 时要写 n-need+2,用 <= 时写 n-need+1——两种写法不能混 2026-11-04 已 AC 27/27
LC 377 组合总和 IV 背包(排列数) 外层 for 上界 < target 应 <= target——目标格 dp[target] 从未计算,7 个用例 4 个全返回 0;213 复盘校准规则:真正规矩是"比较符必须匹配调用合同"——自增递推"最后一个目标位"默认 <=;参数化区间选半开合同(含头不含尾,如 Java subList)就用 <。377 翻车的本质是"想含 target 却写了 <"的合同内部不一致。另:空区间 l==r 有自然写法是半开合同的工程红利 2026-11-09 已 AC 18/18
LC 198 打家劫舍 线性 DP 地基行语义错叠:dp[0] 写成 min(nums[0],nums[1])(想当然"两栋互补")——dp[0] 的世界只有第 0 栋,必须 =nums[0];反例 [5,1,10] 正解 15 vs 错版 11(min 偷换"偷 0 资格"被 dp[2] 踩回)。harness 8 用例全漏因 min/max 多数场景碰巧等效——地基行每格都必须能独立说出前缀语义 2026-11-09 已 AC 70/70
LC 105 前序+中序建树 双序列分治 pix(中序下标)被直接当前序右边界用:build(preL+1, pix) 应为 build(preL+1, preL+leftLen),leftLen = pix - inL。只有 preL == inL(根层)时碰巧对,深层重复包含根 → StackOverflow。反例 pre=[1,2,3], in=[2,3,1] 2026-10-31 已 AC 203/203