leetcode-top100-quickstart

LeetCode Hot 100 快速入门报告

视角:多年未刷算法的工程师 目标:两到四周内把手感找回来,能从容应对面试中 80% 的中等题 语言:Python(语法干净,省下的时间留给思考)


0. 写在前面:这份报告是什么

如果你曾经会写树的递归、会推 DP 转移方程,但工作几年后看到 dfs(node.left) 都要愣两秒——这份报告就是给你的。

不是题解集,也不打算让你刷完 100 道。它做三件事:

  1. 帮你重建套路地图:知道哪类问题对应哪种解法,而不是每题都从零想。
  2. 给你一份40 题的最小可行集:刷完这 40 道,剩下 60 道大多是变种。
  3. 提供逐类模板代码:背下来不是耻辱,是效率。面试官想看你解决问题,不是发明轮子。

读完本报告需要 30 分钟,配套刷题约 40-80 小时(4 周 × 每天 1.5-3 小时)。


1. 你失去的 vs 你还剩的

久疏战阵的人最容易犯两个错:高估自己("我以前会的,看一眼就行")或低估自己("完全不会了,得从头学")。事实是:

你失去的 你还剩的
边界条件的肌肉记忆(off-by-one、空指针) 工程能力(命名、调试、拆解问题)
各种模板代码的瞬时回忆 对复杂度的直觉判断
对题型的快速识别 对系统/数据结构的深刻理解
在白板上无 IDE 写对代码 阅读和理解长代码的能力

结论:你的瓶颈不是"理解力",而是模式识别 + 模板熟练度。所以策略不是"从《算法导论》重读",而是按套路分类,每类刷透 3-5 道,建立条件反射


2. 30 天重启路线图

按"先简单结构,后复杂算法;先模板题,后变种题"的顺序,避免一上来就被 DP 劝退。

周次 主题 重点套路 题量 心态
W1 手感恢复 哈希、双指针、滑动窗口、栈 10-12 把语法和 IDE 找回来
W2 结构题 链表、二叉树、图论基础 10-12 递归和指针的肌肉记忆
W3 搜索类 二分、回溯、堆、贪心 8-10 学会"分类后选模板"
W4 动态规划 一维 DP、背包、多维 DP 8-10 不慌,DP 也是套路

每天的节奏(90 分钟版本):

  • 10 min:复习昨天的题,能在白纸上默写模板就过
  • 60 min:做 1-2 道新题(中等题为主),先想 15 分钟,想不出来直接看题解
  • 20 min:把题解的关键思路用自己的话写在笔记里(不要抄代码

关键纪律

  • ❌ 不要按 LeetCode 题号顺序刷
  • ❌ 不要"想 1 小时还没思路"硬扛——看题解不丢人,复盘才是关键
  • ✅ 同一类题连续刷 3-5 道,强化模式识别
  • ✅ 第二天默写昨天的模板,第七天再默写一次

3. 算法套路地图

一张表看完 Hot 100 的全部套路。看到题先在脑子里过一遍这张表,匹配到哪类就用哪个模板

套路 触发信号(题目长这样就用它) 核心数据结构 Hot 100 占比
哈希 "两个数和为 X"、"找重复/计数" dict / set ~5%
双指针 有序数组找配对、原地操作 两个指针 ~5%
滑动窗口 "连续子数组/子串"满足某条件 双指针 + 计数器 ~5%
前缀和 区间和、子数组和为 K 数组 + 哈希 ~3%
链表 题目给 ListNode 指针 + 虚拟头节点 ~14%
二叉树 题目给 TreeNode 递归 / BFS 队列 ~15%
图/网格 二维矩阵 BFS/DFS、拓扑 队列 + visited ~4%
回溯 "所有方案/排列/组合" 递归 + 状态恢复 ~8%
二分 有序数组找位置、"最小的最大" 左右指针 ~6%
括号匹配、"下一个更大元素" stack / 单调栈 ~5%
"Top K"、动态中位数 heapq ~3%
贪心 "最少次数/最远距离" 一次遍历 ~4%
DP "最值/方案数"且无法贪心 一维/二维数组 ~15%
技巧题 位运算、摩尔投票、原地哈希 看具体题 ~8%

记忆口诀

  • 配对找数 → 哈希
  • 有序/原地 → 双指针
  • 连续子串 → 滑动窗口
  • 区间和 → 前缀和
  • 所有方案 → 回溯
  • Top K → 堆
  • 最值方案数 → DP

4. 十五大套路逐个击破

每类的结构:直觉 → 模板 → 必刷题 → 易错点


4.1 哈希表

直觉:用空间换时间,把"O(n) 查找"变成"O(1) 查找"。看到"找一个数"先想"能不能预先记下来"。

模板

# 两数之和(典型套路)
def twoSum(nums, target):
    seen = {}  # value -> index
    for i, x in enumerate(nums):
        if target - x in seen:
            return [seen[target - x], i]
        seen[x] = i

必刷题(3 道)

  • 1. 两数之和 — 模板题
  • 49. 字母异位词分组 — key 用 sorted(s) 或 26 字母计数元组
  • 128. 最长连续序列 — 关键:只从"序列起点"开始数(x-1 not in set

易错点

  • dict 的 value 存 index 还是 count?想清楚再写
  • 第 128 题不优化的写法是 O(n²),必须只从起点开始

4.2 双指针

直觉:在有序原地修改的数组上,两个指针往中间走(对撞)或同方向走(快慢)。

模板

# 对撞指针:三数之和
def threeSum(nums):
    nums.sort()
    res = []
    for i in range(len(nums) - 2):
        if i > 0 and nums[i] == nums[i-1]: continue  # 去重
        l, r = i + 1, len(nums) - 1
        while l < r:
            s = nums[i] + nums[l] + nums[r]
            if s == 0:
                res.append([nums[i], nums[l], nums[r]])
                while l < r and nums[l] == nums[l+1]: l += 1
                while l < r and nums[r] == nums[r-1]: r -= 1
                l += 1; r -= 1
            elif s < 0: l += 1
            else: r -= 1
    return res

必刷题(4 道)

  • 283. 移动零 — 快慢指针入门
  • 11. 盛最多水的容器 — 对撞指针,关键证明"短板移动"
  • 15. 三数之和 — 排序 + 双指针,面试高频
  • 42. 接雨水 — 对撞指针 / 单调栈 两种解法都要会

易错点

  • 三数之和的去重i > 0 and nums[i] == nums[i-1] 是 i 的去重,循环内是 l/r 的去重
  • 接雨水推荐先用双指针(O(1) 空间),单调栈作为加分项

4.3 滑动窗口

直觉:双指针的变种。窗口 = [l, r],r 一直右移扩张,条件被打破时 l 才右移收缩

模板(背下来):

def slidingWindow(s):
    cnt = {}
    l = 0
    ans = 0
    for r in range(len(s)):
        # 1. 把 s[r] 加入窗口
        cnt[s[r]] = cnt.get(s[r], 0) + 1
        # 2. 窗口不满足条件就收缩 l
        while window_invalid():
            cnt[s[l]] -= 1
            if cnt[s[l]] == 0: del cnt[s[l]]
            l += 1
        # 3. 更新答案
        ans = max(ans, r - l + 1)
    return ans

必刷题(3 道)

  • 3. 无重复字符的最长子串 — 模板题
  • 438. 找到字符串中所有字母异位词 — 定长窗口
  • 76. 最小覆盖子串 — 变长窗口,难度上一档,面试高频

易错点

  • 窗口长度公式:r - l + 1
  • "定长窗口" vs "变长窗口" 是两种写法,76 题是后者
  • 记得在 cnt[c] == 0 时把 key 删掉,否则比较哈希字典会出错

4.4 前缀和

直觉区间和 = 前缀和之差。处理"子数组和"时几乎必用。

模板

# 和为 K 的子数组
def subarraySum(nums, k):
    pre_count = {0: 1}  # 前缀和 -> 出现次数
    pre_sum = 0
    ans = 0
    for x in nums:
        pre_sum += x
        # 如果存在某个前缀和 = pre_sum - k,就有对应的子数组
        ans += pre_count.get(pre_sum - k, 0)
        pre_count[pre_sum] = pre_count.get(pre_sum, 0) + 1
    return ans

必刷题(2 道)

  • 560. 和为 K 的子数组 — 前缀和 + 哈希经典组合
  • 238. 除自身以外数组的乘积 — 前缀积 + 后缀积思想

易错点

  • pre_count[0] = 1 这一句别忘了,处理"从下标 0 开始"的情况
  • 不要先把所有前缀和算好再查询,边算边查才是 O(n)

4.5 链表

直觉:链表题 90% 用三个技巧:虚拟头节点(dummy)、快慢指针、画图。先画图再写代码。

模板 - 反转链表(必背):

def reverseList(head):
    prev, cur = None, head
    while cur:
        nxt = cur.next
        cur.next = prev
        prev = cur
        cur = nxt
    return prev

模板 - 快慢指针找环

def hasCycle(head):
    slow = fast = head
    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next
        if slow == fast: return True
    return False

必刷题(8 道,按难度排序)

  • 206. 反转链表 — 模板题,必须默写
  • 21. 合并两个有序链表 — 递归 / 迭代两种写法
  • 141. 环形链表 — 快慢指针入门
  • 142. 环形链表 II — 快慢指针 + 数学(Floyd 判圈)
  • 160. 相交链表 — 双指针走两遍
  • 19. 删除倒数第 N 个节点 — 快慢指针 + dummy
  • 25. K 个一组翻转链表 — 反转模板的进阶应用
  • 146. LRU 缓存 — 双向链表 + 哈希,面试超高频

易错点

  • 任何"可能删除头节点"的题,先建 dummy = ListNode(0, head),最后返回 dummy.next
  • 反转链表前一定要先保存 next,否则丢链
  • LRU 自己实现双向链表节点比用 OrderedDict 更能展示功力

4.6 二叉树

直觉:二叉树就是递归。问自己三件事:

  1. 递归函数返回什么?(深度?是否平衡?路径和?)
  2. 左右子树各自递归的结果怎么合并?
  3. base case 是什么?(一般是 if not root: return ...

模板 - 通用递归

def dfs(root):
    if not root: return base_value
    left = dfs(root.left)
    right = dfs(root.right)
    # 用 left, right, root.val 合并出当前层的答案
    return combine(left, right, root.val)

模板 - 层序遍历(BFS)

from collections import deque
def levelOrder(root):
    if not root: return []
    q = deque([root])
    res = []
    while q:
        level = []
        for _ in range(len(q)):  # 关键:固定本层节点数
            node = q.popleft()
            level.append(node.val)
            if node.left: q.append(node.left)
            if node.right: q.append(node.right)
        res.append(level)
    return res

必刷题(10 道)

  • 94. 中序遍历 — 递归 + 迭代(栈)两种写法
  • 104. 最大深度 — 最简单的递归入门
  • 226. 翻转二叉树 — Homebrew 作者翻车题,必会
  • 101. 对称二叉树 — 双指针式递归
  • 102. 层序遍历 — BFS 模板
  • 199. 二叉树右视图 — BFS 取每层最后一个
  • 543. 二叉树直径 — "返回深度,更新全局答案"模式
  • 98. 验证 BST — 用上下界递归,不要只比较父子
  • 236. 最近公共祖先 — 经典递归思维题
  • 124. 二叉树最大路径和 — 直径题的高阶版,面试高频

进阶(可选)

  • 105. 从前序与中序构造二叉树 — 分治
  • 437. 路径总和 III — 前缀和在树上的应用
  • 114. 展开为链表 — 递归 + 反向中序

易错点

  • 验证 BST 不能只 root.left.val < root.val < root.right.val,必须传上下界
  • 直径题:递归函数返回深度,但用全局变量记录最大直径
  • 层序遍历的 for _ in range(len(q)) 必须先取 len 再循环,否则会越界

4.7 图与网格

直觉:网格题(岛屿、腐烂橘子)= 在二维数组上 BFS/DFS。图论题(课程表)= 拓扑排序。

模板 - 网格 DFS

def numIslands(grid):
    if not grid: return 0
    m, n = len(grid), len(grid[0])
    def dfs(i, j):
        if i < 0 or i >= m or j < 0 or j >= n or grid[i][j] != '1':
            return
        grid[i][j] = '0'  # 原地改 visited
        for di, dj in [(-1,0),(1,0),(0,-1),(0,1)]:
            dfs(i+di, j+dj)
    count = 0
    for i in range(m):
        for j in range(n):
            if grid[i][j] == '1':
                count += 1
                dfs(i, j)
    return count

模板 - 拓扑排序

from collections import defaultdict, deque
def canFinish(numCourses, prerequisites):
    graph = defaultdict(list)
    indegree = [0] * numCourses
    for a, b in prerequisites:
        graph[b].append(a)
        indegree[a] += 1
    q = deque([i for i in range(numCourses) if indegree[i] == 0])
    visited = 0
    while q:
        node = q.popleft()
        visited += 1
        for nxt in graph[node]:
            indegree[nxt] -= 1
            if indegree[nxt] == 0:
                q.append(nxt)
    return visited == numCourses

必刷题(4 道)

  • 200. 岛屿数量 — DFS 模板题
  • 994. 腐烂的橘子 — 多源 BFS
  • 207. 课程表 — 拓扑排序模板题
  • 208. 实现 Trie — 字典树数据结构

易错点

  • 网格题用"原地改"代替 visited 数组省内存,但要确认题目允许修改
  • 多源 BFS 是把所有起点先全部入队,不是只放一个
  • 拓扑排序用 BFS(Kahn 算法)比 DFS 更不容易写错

4.8 回溯

直觉:枚举"所有方案"。三件套:选择 → 递归 → 撤销

通用模板(必背):

def backtrack(path, choices):
    if 满足结束条件:
        res.append(path[:])  # 注意拷贝
        return
    for choice in choices:
        if 不合法: continue
        path.append(choice)        # 选择
        backtrack(path, new_choices)  # 递归
        path.pop()                 # 撤销

必刷题(6 道,难度递增)

  • 78. 子集 — "选或不选"模板
  • 46. 全排列 — 用 used 数组的模板
  • 17. 电话号码字母组合 — 树形回溯入门
  • 39. 组合总和 — 元素可重复用,用 start 控制顺序
  • 22. 括号生成 — 用"剩余左右括号数"剪枝
  • 79. 单词搜索 — 网格 + 回溯,要 visited

进阶

  • 131. 分割回文串 — 切片回溯
  • 51. N 皇后 — 经典难题,加分项

易错点

  • res.append(path[:]) 必须是拷贝,不然后续 path 修改会污染结果
  • 组合题用 start 控制顺序避免重复,排列题用 used[] 标记
  • 单词搜索的 visited 必须在递归后撤销

4.9 二分查找

直觉只要存在"单调性"就能二分。不一定数组本身要有序,比如"在 [1, n] 中找最小的满足条件 X 的数"也可以二分。

模板(闭区间版本,背这个就够了)

def binarySearch(nums, target):
    l, r = 0, len(nums) - 1
    while l <= r:
        mid = (l + r) // 2
        if nums[mid] == target:
            return mid
        elif nums[mid] < target:
            l = mid + 1
        else:
            r = mid - 1
    return -1  # 或 l,看题目要返回插入位置时

必刷题(5 道)

  • 35. 搜索插入位置 — 标准二分
  • 34. 在排序数组中查找第一个和最后一个位置 — 左右边界二分
  • 74. 搜索二维矩阵 — 把矩阵当一维数组
  • 153. 寻找旋转排序数组中的最小值 — "旋转数组"思维
  • 33. 搜索旋转排序数组 — 上一题的进阶

地狱难度(可跳过)

  • 4. 寻找两个正序数组的中位数 — Hard,二分边界极绕,初学者不必硬攻

易错点

  • 死循环:l <= rmid + 1 / mid - 1这一组绝对不会死循环
  • "找第一个 >= target"和"找最后一个 <= target"是两种写法,建议背一个模板(推荐用 bisect_left/bisect_right 的实现思路)

4.10 栈与单调栈

直觉

  • 普通栈:括号匹配、撤销操作。
  • 单调栈:找"下一个更大/更小的元素",几乎是固定套路

模板 - 单调栈(找下一个更大元素)

def dailyTemperatures(T):
    n = len(T)
    res = [0] * n
    stack = []  # 存下标,对应的温度是递减的
    for i in range(n):
        while stack and T[stack[-1]] < T[i]:
            j = stack.pop()
            res[j] = i - j
        stack.append(i)
    return res

必刷题(5 道)

  • 20. 有效的括号 — 栈入门
  • 155. 最小栈 — 辅助栈技巧
  • 394. 字符串解码 — 双栈模拟
  • 739. 每日温度 — 单调栈模板题
  • 84. 柱状图中最大的矩形 — 单调栈 Hard,面试高频

易错点

  • 单调栈一般存下标而不是值,方便算距离
  • 84 题的技巧:在数组前后加哨兵 [0],省去边界判断

4.11 堆

直觉"Top K"问题、"动态求中位数"几乎必用堆。Python 的 heapq小顶堆,要大顶堆就存负数。

模板 - Top K(最大 K 个)

import heapq
def topK(nums, k):
    # 维护一个大小为 k 的小顶堆
    heap = []
    for x in nums:
        heapq.heappush(heap, x)
        if len(heap) > k:
            heapq.heappop(heap)
    return heap  # 堆里就是前 k 大

必刷题(3 道)

  • 215. 数组中的第 K 个最大元素 — 堆 / 快速选择两种解法
  • 347. 前 K 个高频元素 — 堆 + 哈希
  • 295. 数据流的中位数 — 大顶堆 + 小顶堆,面试经典

易错点

  • 前 K 大小顶堆(淘汰小的),反之亦然——这点容易绕晕
  • 295 题维护两个堆,大顶堆装较小的一半,差值不超过 1

4.12 贪心

直觉:每一步选当前最优,不回头。关键是要证明贪心策略正确——但面试时观察 + 直觉即可,证明是数学家的工作。

必刷题(4 道)

  • 121. 买卖股票的最佳时机 — "维护最小值"贪心
  • 55. 跳跃游戏 — 维护"能到达的最远位置"
  • 45. 跳跃游戏 II — 上一题的进阶(最少跳几次)
  • 763. 划分字母区间 — 预处理 + 贪心

易错点

  • 贪心和 DP 经常长得像,先想能不能贪心(更简单),不行再上 DP
  • "跳跃游戏"系列的关键是维护一个边界

4.13 动态规划(一维)

直觉:DP 三件套——

  1. 定义状态dp[i] 是什么?
  2. 写转移方程dp[i] 怎么从 dp[i-1]dp[i-2] 推出?
  3. 初始化和边界dp[0] 是多少?

口诀"最值/方案数 + 无后效性" 就用 DP。无后效性 = 当前状态只依赖过去,不依赖未来。

模板 - 打家劫舍

def rob(nums):
    if not nums: return 0
    if len(nums) == 1: return nums[0]
    dp = [0] * len(nums)
    dp[0] = nums[0]
    dp[1] = max(nums[0], nums[1])
    for i in range(2, len(nums)):
        dp[i] = max(dp[i-1], dp[i-2] + nums[i])
    return dp[-1]

必刷题(6 道,按难度递增)

  • 70. 爬楼梯 — DP 入门(其实就是斐波那契)
  • 198. 打家劫舍 — 经典一维 DP
  • 53. 最大子数组和 — Kadane 算法(DP 的特例)
  • 300. 最长递增子序列 — O(n²) DP + 二分优化到 O(n log n)
  • 322. 零钱兑换 — 完全背包入门
  • 139. 单词拆分 — 字符串 + DP

进阶

  • 152. 乘积最大子数组 — 同时维护 max 和 min(因为负数)
  • 416. 分割等和子集 — 01 背包模板
  • 279. 完全平方数 — 完全背包

易错点

  • 53 题的 DP 状态是"以 i 结尾的最大子数组和",不是"前 i 个的最大和"
  • 322 题用 dp[i] = min(dp[i], dp[i-coin] + 1),初始化为 inf
  • 大多数一维 DP 都能空间优化到 O(1)(用两三个变量代替数组)

4.14 动态规划(多维)

直觉:状态有两个维度(比如两个字符串、二维网格)。状态定义往往是 dp[i][j] = "前 i 个 X 和前 j 个 Y 的某指标"。

模板 - 最长公共子序列

def longestCommonSubsequence(s1, s2):
    m, n = len(s1), len(s2)
    dp = [[0] * (n+1) for _ in range(m+1)]
    for i in range(1, m+1):
        for j in range(1, n+1):
            if s1[i-1] == s2[j-1]:
                dp[i][j] = dp[i-1][j-1] + 1
            else:
                dp[i][j] = max(dp[i-1][j], dp[i][j-1])
    return dp[m][n]

必刷题(5 道)

  • 62. 不同路径 — 二维 DP 入门
  • 64. 最小路径和 — 同上变种
  • 5. 最长回文子串 — 中心扩展 / DP 两种解法
  • 1143. 最长公共子序列 — 双串 DP 模板
  • 72. 编辑距离 — 双串 DP 王者,面试超高频

易错点

  • 双串 DP 的下标对齐:dp[i][j] 通常对应 s1[i-1]s2[j-1](因为多了 0 行 0 列)
  • 编辑距离的三种操作(插入、删除、替换)对应 dp[i-1][j]dp[i][j-1]dp[i-1][j-1],画图理解

4.15 技巧题

这一类不在主线套路里,但 Hot 100 占比不小,面试爱考因为"想到就过、想不到就跪"

必刷题(5 道)

  • 136. 只出现一次的数字异或a ^ a = 0
  • 169. 多数元素摩尔投票
  • 31. 下一个排列 — 找规律 + 双指针
  • 75. 颜色分类 — 三指针(荷兰国旗)
  • 287. 寻找重复数 — 快慢指针在数组上的应用(Floyd 判圈)

易错点

  • 这类题不必硬想,记住套路名字就好
  • 异或的三条性质:a^0=aa^a=0、满足交换律——刷题一辈子能用十次

5. 精选 40 题刷题清单

优先级 P0(必刷,20 题):模板题 + 高频题。刷完这 20 题,面试 50% 中等题能稳过。

# 题目 套路 难度
1 两数之和 哈希 Easy
15 三数之和 双指针 Medium
3 无重复字符的最长子串 滑动窗口 Medium
560 和为 K 的子数组 前缀和 Medium
53 最大子数组和 DP Medium
206 反转链表 链表 Easy
21 合并两个有序链表 链表 Easy
141 环形链表 快慢指针 Easy
146 LRU 缓存 链表+哈希 Medium
104 二叉树最大深度 递归 Easy
102 二叉树层序遍历 BFS Medium
236 最近公共祖先 递归 Medium
200 岛屿数量 DFS Medium
46 全排列 回溯 Medium
78 子集 回溯 Medium
20 有效的括号 Easy
215 第 K 大的元素 Medium
121 买卖股票最佳时机 贪心 Easy
70 爬楼梯 DP Easy
198 打家劫舍 DP Medium

优先级 P1(强化训练,15 题):每类的进阶题。

# 题目 套路 难度
128 最长连续序列 哈希 Medium
11 盛最多水的容器 双指针 Medium
76 最小覆盖子串 滑动窗口 Hard
142 环形链表 II 链表 Medium
25 K 个一组翻转链表 链表 Hard
98 验证 BST 递归 Medium
124 二叉树最大路径和 递归 Hard
199 二叉树右视图 BFS Medium
207 课程表 拓扑排序 Medium
39 组合总和 回溯 Medium
22 括号生成 回溯 Medium
33 搜索旋转排序数组 二分 Medium
739 每日温度 单调栈 Medium
322 零钱兑换 DP Medium
72 编辑距离 DP Hard

优先级 P2(加分项,5 题):硬骨头,刷完显著拉开差距。

# 题目 套路 难度
42 接雨水 双指针/单调栈 Hard
84 柱状图最大矩形 单调栈 Hard
295 数据流的中位数 双堆 Hard
300 最长递增子序列 DP + 二分 Medium
4 两个正序数组中位数 二分 Hard

刷完顺序建议:P0 全刷 → 回头复习 P0 默写 → P1 全刷 → P2 选做。


6. 复盘心法

刷题不是输入题量,是输出模式识别。下面六条是给"久疏战阵"的人最有效的:

  1. 看题先识别套路,再写代码。如果看完题没想到属于哪类,先看第 3 节那张表。
  2. 15 分钟想不出就看题解。看题解不是失败,第二天默写才是真复习。
  3. 每周日做"默写测试":白纸上默写本周学过的所有模板(5-7 个),写不出来的回去重做对应题。
  4. 同类题连刷,不要今天哈希明天 DP 后天链表,那是浪费时间。
  5. 每道题写一句话题解,写到自己的笔记里。一年后回头看一句话就能想起整道题。
  6. 拒绝完美主义:100 道题不必全刷,40 道刷透 > 80 道刷过。

7. 常见陷阱速查

陷阱 表现 对策
只看题解不动手 "我看懂了" → 第二天忘光 强制白纸默写
刷题不分类 按题号顺序刷,毫无套路感 按本报告的 15 类刷
死磕一道题 2 小时 自我感动,效率极低 15 分钟为界,超时看题解
收藏夹吃灰 收藏 200 篇题解从不看 只收藏 5 类核心模板
追求一遍过 害怕看题解,刷得慢 第一遍允许看,第三遍要求独立
只刷 Easy 信心爆棚但面试翻车 70% 时间花在 Medium
跳过 DP "我不擅长 DP" DP 是最套路化的,反而最容易补

8. 4 周后你应该长什么样

  • 看到"两数 / 配对" → 立刻想到哈希
  • 看到"子数组连续" → 立刻想到滑动窗口或前缀和
  • 看到 TreeNode → 手指开始打字 if not root: return
  • 看到"所有方案" → 立刻拿出回溯三件套
  • 看到"最值且无后效性" → 开始定义 dp[i]
  • 拿到一道新中等题,5 分钟内能说出大致思路,30 分钟内能写完调通

做到这些,面试中等题命中率 70%+,Hot 100 也算是真正"刷完"了。


附录:本报告引用的所有题目

按出现顺序列出(共 60+ 道,覆盖 Hot 100 的核心 ~60%):

哈希:  1, 49, 128
双指针: 11, 15, 42, 283
滑窗:  3, 76, 438
前缀和: 238, 560
链表:  19, 21, 25, 141, 142, 146, 160, 206
二叉树: 94, 98, 101, 102, 104, 105, 114, 124, 199, 226, 236, 437, 543
图论:  200, 207, 208, 994
回溯:  17, 22, 39, 46, 51, 78, 79, 131
二分:  4, 33, 34, 35, 74, 153
栈:    20, 84, 155, 394, 739
堆:    215, 295, 347
贪心:  45, 55, 121, 763
DP:    5, 53, 62, 64, 70, 72, 139, 152, 198, 279, 300, 322, 416, 1143
技巧:  31, 75, 136, 169, 287

祝刷题愉快。多年未刷不是问题,找对方法 4 周就能回到状态。