LeetCode 怎么刷:方法论与节奏
这一课你将能做到
- 制定一份按主题推进的 8~12 周刷题计划,并知道每天该做什么
- 用固定的「复盘模板」记录每道题,而不是刷过就忘
- 看懂 Big-O 复杂度表,能在动笔前判断一种思路会不会超时
为什么要学
很多初学者刷 LeetCode 的方式是:打开题目 → 想不出来 → 看题解 → 抄一遍 → 提交,绿色 Accepted → 下一题。两个月后刷了 200 道,面试时遇到做过的变体还是写不出来。问题不在智商,而在方法:刷题刷的是「模式识别」,不是记忆力。
本站的在线判题平台和 LeetCode 本质是同一类系统:你把 Java 代码提交上去,平台用预设的输入数据运行,比对输出,返回「通过 / 答案错误 / 超时 / 越界」。以后笔试、面试的在线编程环节也都是这个形态。所以这门课不仅教算法,也在训练你适应「读题 → 编码 → 提交 → 看反馈」这套真实流程。
本课先解决「怎么刷」,后面 11 课解决「刷什么、怎么想」。
先建立图像
一道题从读到交,建议固定走这五步:
读题(3 分钟)
→ 看输入规模 n 有多大、数据是否有序、有没有重复
想模式(5~10 分钟)
→ 这题像哪一类?哈希?双指针?二分?DFS?DP?
写代码(15~25 分钟)
→ 先写主流程,再补边界:null、空数组、单个元素、重复值
手算验证(3 分钟)
→ 拿最小用例在纸上走一遍,面试没有调试器
复盘(5 分钟)
→ 套模板记录:卡点、模式、可优化点
高频模式地图(本课后半部分逐个攻克):
| 模式 | 一句话直觉 | 对应课 |
|---|---|---|
| 数组 + 哈希 | 用空间换时间,把「查找」变成 O(1) | 第 2 课 |
| 双指针 / 滑动窗口 | 两个下标配合,把双重循环压成一次扫描 | 第 3、6 课 |
| 栈 | 「最近的、未匹配的」问题 | 第 4 课 |
| 二分查找 | 有序数据上每次排除一半 | 第 5 课 |
| 链表 / 树 / 堆 | 指针操作、递归、优先队列 | 第 7~9 课 |
| 回溯 / 图 | 系统性枚举所有可能、遍历节点关系 | 第 10、11 课 |
| 动态规划 | 把大问题拆成有重叠的小问题,记结果 | 第 12 课 |
跟着做
步骤 1:用复杂度反推解法
题目给 n 的范围,就能反推允许什么复杂度。这是读题后第一件事:
| 复杂度 | n 上限(大约) | 典型算法 |
|---|---|---|
| O(n!)、O(2ⁿ) | n ≤ 20 | 暴力枚举、回溯 |
| O(n²) | n ≤ 10⁴ | 双重循环 |
| O(n log n) | n ≤ 10⁶ | 排序、堆 |
| O(n)、O(log n) | n ≤ 10⁸ | 单次扫描、二分 |
如果题目说 nums.length <= 10^5,你构思出 O(n²) 解法时就该立刻警觉:大约 10¹⁰ 次运算,必然超时,必须换哈希或双指针。先估复杂度,再写代码,能省下大量无效提交。
步骤 2:体验两种模式解两道入门题
题 1:LeetCode 1「两数之和」(简单)——给定数组 nums 和目标值 target,返回和为 target 的两个元素下标。
暴力做法是双重循环 O(n²)。注意到「对于每个数 x,我要快速知道 target - x 出现过没有」,这正是哈希表的用途:
import java.util.HashMap;
import java.util.Map;
class Solution {
public int[] twoSum(int[] nums, int target) {
// 值 -> 它的下标
Map<Integer, Integer> seen = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int need = target - nums[i];
if (seen.containsKey(need)) {
return new int[]{seen.get(need), i};
}
seen.put(nums[i], i);
}
return new int[]{}; // 题目保证有解,这行只是让编译器满意
}
}
逐行理解:边走边把「见过的值 → 下标」存进 map;走到 i 时先查缺的数在不在历史里,在就直接返回两个下标。时间 O(n),空间 O(n)。这就是「用空间换时间」最经典的一次体验。
题 2:LeetCode 704「二分查找」(简单)——在升序数组中找 target,返回下标,找不到返回 -1。
数据有序,就没必要逐个看:每次猜中间,猜错直接排除一半。
class Solution {
public int search(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while (left <= right) { // 注意是 <=,区间里还剩一个元素也要查
int mid = left + (right - left) / 2; // 防溢出,不要写 (left + right) / 2
if (nums[mid] == target) {
return mid;
} else if (nums[mid] < target) {
left = mid + 1; // mid 已查过,跳过它
} else {
right = mid - 1;
}
}
return -1;
}
}
时间 O(log n):100 万个元素最多猜 20 次。空间 O(1)。这两题放在一起体会:同样是「找」,数据特征不同(无序配对 vs 有序查找),模式完全不同。
步骤 3:制定你的刷题计划
推荐 8 周节奏(在职,每天 1~1.5 小时):
| 周次 | 主题 | 题量 |
|---|---|---|
| 第 1 周 | 数组 + 哈希 | 每天 2 题,先简单后中等 |
| 第 2 周 | 双指针 + 滑动窗口 | 每天 1~2 题 |
| 第 3 周 | 栈 + 二分查找 | 每天 1~2 题 |
| 第 4 周 | 链表 | 每天 1~2 题,重点画图 |
| 第 5 周 | 二叉树 + 堆 | 每天 1~2 题 |
| 第 6 周 | 回溯 + 图 | 每天 1 题,重在理解模板 |
| 第 7 周 | 动态规划入门 | 每天 1 题 |
| 第 8 周 | 混合复习 + 模拟周测 | 每天 2 题随机抽 |
规则:每道题先独立想 20 分钟;超时还没思路就看题解,但看懂后必须关掉题解自己默写一遍,并在 3 天后二刷。
步骤 4:按主题刷 vs 随机刷
- 入门阶段(前 6~7 周)必须按主题刷。连续做 10 道哈希题,大脑会自动归纳「什么信号触发哈希」,这是随机刷题给不了的刻意练习。
- 冲刺阶段(最后 1~2 周)改为随机刷 / 套卷模拟。因为真实面试不会告诉你「这题用双指针」,你需要练习从题目本身识别模式。
- 一句话:按主题学模式,随机混合验真功。
步骤 5:用复盘模板记录每题
建议用一个表格或笔记软件,每题提交通过后立刻填:
题号 / 题名 / 难度 / 日期
模式:这题属于哪一类?我最初想到的是什么?
卡点:我卡在了哪一步?(审题?模式?边界?代码实现?)
关键一句:用一句话说清这题的核心动作
易错点:边界条件、溢出、空指针
复杂度:时间 __ / 空间 __
二刷日期:3~7 天后,结果:独立写出 / 又卡了
「卡点」一栏最重要。它会诚实告诉你:如果总卡在「模式想不出」,说明同主题题量不够;如果总卡在「边界」,说明写代码习惯有问题。针对性补,比刷新题有效得多。
讲清楚要点
- Accepted 不是终点,能在白纸上默写才是:看题解觉得懂了,是「识别记忆」;关掉答案写出来,才是「提取能力」,面试考的是后者。
- 复杂度是解题的约束条件,不是事后补充:先看 n 的范围反推允许的复杂度,能在动手前排除死路。
- 质量 > 数量:精选 150 道高频题、每题二刷三刷,远胜于囫囵吞枣 500 道。
- 卡题限时是保护自尊也是提高效率:20 分钟无思路就看题解,别和一道题硬耗一整天。
- 提交失败是正常反馈,不是能力判决:在线判题平台的 WA/TLE 告诉你具体哪里不对,读反馈、改、再交,这本身就是实战流程。
你可能会懵的地方
-
我 Java 语法还不熟,能开始刷吗? 可以。简单题只需要循环、数组、HashMap、ArrayList。语法不熟就在刷题中查,前 20 题会慢,之后越来越顺,这比先啃完一本语法书高效。
-
一道题想多久算「够」? 入门阶段 15~20 分钟。完全没思路说明模式还没学过,硬想一小时只是内耗;看题解学习,然后安排二刷。
-
简单题有必要刷吗?直接冲中等行不行? 每个主题前 2~3 道简单题是用来「固化模板」的,值得刷;但同一个套路的简单题刷 5 道以上就是重复劳动,应尽快进入中等题。
-
题解代码和我的写法不一样,要不要背标准答案? 不背具体代码,背「关键动作」。同一个模式有多种等价写法,你能讲清思路、代码无 bug、复杂度正确,就是好答案。
-
要不要刷困难题? 初、中级后端面试,简单 + 中等覆盖 90% 的场次。困难题等 150 道中等题熟练后,按目标公司的出题风格再挑,不必硬啃。
错法对照
| 错法 | 问题 | 正解 |
|---|---|---|
| 看完题解点提交就进下一题 | 只有短期记忆,三天后全忘 | 关题解默写 + 3 天后二刷 |
| 按题号顺序从第 1 题刷到第 500 题 | 模式无法归纳,进步缓慢 | 入门期按主题集中刷 |
| 写完不估复杂度 | 面试被问「能不能优化」时答不上 | 读题先看 n 范围,动笔前估复杂度 |
| 一出错就本地疯狂打断点 | 依赖调试器,手写面试时不会查错 | 先手算小用例定位问题 |
| 追求一天刷 8 题的数量 | 每题都半生不熟 | 每天 1~2 题吃透 + 复盘 |
卡点急救
- 看到题大脑一片空白:别慌,这是模式库还没建立。先问自己三个问题——数据有序吗?需要反复「查找」吗?有没有「最近/配对」关系?分别对应二分、哈希、栈。实在没思路就看题解学模式。
- 本地能过、提交后答案错误:八成是边界没考虑——空输入、单元素、重复值、负数。用平台给的失败用例在纸上手算,而不是瞎改代码碰运气。
- 提交后超时(TLE):说明复杂度不达标。检查有没有双重循环可以被哈希 / 双指针 / 二分替掉,而不是去优化循环里的语句。
面试常问
-
你平时怎么刷算法题? 按主题刻意练习,每个模式做 5~8 道固化模板;每道题限时独立思考,超时再看题解;用复盘表记录卡点,3~7 天后二刷;后期做随机套卷模拟真实面试。这个回答展示的是「方法论」,比说「我刷了 300 道」有说服力。
-
做题时怎么想到要用某个数据结构? 从「我需要什么操作」反推:需要 O(1) 查找就用哈希;需要按顺序处理「最近」元素就用栈;需要反复取最大/最小值就用堆;数据有序且要找目标就用二分。
-
如果面试题完全没见过怎么办? 先大声澄清题意和边界,再从暴力解法入手(保证有解可讲),然后分析暴力解的瓶颈在哪一步,用合适的数据结构或模式优化那一步。面试官看的是推导过程,不是等一个标准答案。
自测三问
- 给你 n 的范围,你能不能 10 秒内反推允许的最高复杂度?
- 按主题刷和随机刷分别适合什么阶段?为什么?
- 你的复盘模板里,哪一栏能帮你定位「为什么这题没做出来」?
小结一句话
刷题拼的不是数量和记性,而是「模式识别 + 边界意识 + 复杂度判断」,用对计划和复盘,150 道精题胜过 500 道流水账。
延伸
- 立刻实践:LeetCode 1 两数之和、LeetCode 704 二分查找,在本站在线判题平台提交你的第一次答案
- 配套阅读:Big-O 速查表与本课程路线图
- 下一课预告:数组与哈希——LeetCode 最高频的起手式,拿下两数之和、字母异位词分组等经典题