LeetCode 刷题策略全解析(2026 更新):如何高效刷题,少走弯路
LeetCode高效刷题策略全解析2026:从题目分类、刷题节奏到面试实战。避免题海战术,用系统方法提升刷题效率,掌握面试高频题型与解题套路。 本文基于真实面经整理,附详细准备策略。
候选人:李明(化名) 目标岗位:Google SDE 刷题经历:3 个月刷完 Blind 75 + Meta 高频 30 题,一次性通过电话面试和 VO
“我刚开始刷 LeetCode 的时候也是毫无头绪,每天随机刷 10 道,结果一个月过去了,面试还是不会做。后来我意识到,刷题不是拼数量,而是拼模式识别。”
今天我就分享这套经过实战验证的 LeetCode 高效刷题策略,帮你少走弯路,快速上岸。
一、核心模式:10 类必掌握算法模板
LeetCode 上 3000+ 题目,真正考面试的核心模式不超过 10 种。掌握这 10 个模板,你可以覆盖 80% 以上的面试题目。
模式 1:滑动窗口(Sliding Window)
核心思路:维护一个窗口 [left, right],根据条件动态调整窗口大小。
适用场景:子串/子数组问题、固定长度或可变长度的连续区间。
# 通用模板
def sliding_window(s, target):
left = 0
result = float('inf')
for right in range(len(s)):
# 扩展窗口:添加右边界元素
# ... update state ...
# 收缩窗口:当满足条件时,尝试缩小左边界
while condition_met:
result = min(result, right - left + 1)
# ... remove left element ...
left += 1
return result
经典题目:
- 3. Longest Substring Without Repeating Characters — 最长无重复子串
- 30. Substring with Concatenation of All Words — 固定窗口滑动
- 76. Minimum Window Substring — 最小覆盖子串(Hard)
实战对话:
面试官:给一个字符串,找出最长无重复字符的子串长度。
我:我可以用滑动窗口来做。维护一个哈希表记录字符最后出现的位置,当遇到重复字符时,把左边界跳到重复位置之后。时间复杂度 O(n),空间 O(字符集大小)。
面试官:好,写一下代码?
我:
def lengthOfLongestSubstring(s: str) -> int: char_map = {} left = max_len = 0 for right, char in enumerate(s): if char in char_map and char_map[char] >= left: left = char_map[char] + 1 char_map[char] = right max_len = max(max_len, right - left + 1) return max_len面试官:不错,那如果要求返回这个子串本身呢?
我:那就需要记录最大长度时的左右边界,最后切片返回就可以了。
模式 2:双指针(Two Pointers)
核心思路:利用有序性或对称性,用两个指针从两端或同一起点向中间/同一方向移动。
适用场景:排序数组找目标和、链表反转、回文判断。
# 排序数组中找两个数和为 target
def two_sum(sorted_arr: list, target: int) -> list:
left, right = 0, len(sorted_arr) - 1
while left < right:
curr = sorted_arr[left] + sorted_arr[right]
if curr == target:
return [left, right]
elif curr < target:
left += 1
else:
right -= 1
return [-1, -1]
经典题目:
- 1. Two Sum — 最经典(但注意这题是未排序的,需要先 hash)
- 15. 3Sum — 三数之和(排序 + 双指针)
- 11. Container With Most Water — 盛最多水的容器
- 167. Two Sum II - Input Array Is Sorted — 排序数组两数之和
模式 3:快慢指针(Fast & Slow Pointers)
核心思路:一个指针走一步,另一个走两步,用于检测循环或找中点。
适用场景:链表环检测、找中点、删除第 N 个节点。
# 判断链表是否有环
def hasCycle(head: ListNode) -> bool:
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast: # 相遇说明有环
return True
return False
经典题目:
- 141. Linked List Cycle — 链表环检测
- 142. Linked List Cycle II — 找环入口
- 876. Middle of the Linked List — 找中点
- 287. Find the Duplicate Number — 找重复数(Floyd 判圈法)
模式 4:合并区间(Merge Intervals)
核心思路:先按起点排序,然后逐个比较当前区间与合并列表最后一个区间的关系。
def merge(intervals: list) -> list:
if not intervals:
return []
intervals.sort(key=lambda x: x[0])
merged = [intervals[0]]
for current in intervals[1:]:
prev = merged[-1]
if current[0] <= prev[1]: # 重叠
prev[1] = max(prev[1], current[1])
else:
merged.append(current)
return merged
经典题目:
- 56. Merge Intervals — 合并区间
- 57. Insert Interval — 插入区间
- 986. Interval List Intersections — 区间交集
- 759. Employee Free Time — 员工空闲时间
模式 5:BFS(广度优先搜索)
核心思路:逐层遍历,使用队列,适合找最短路径。
from collections import deque
def bfs(graph, start, target):
visited = {start}
queue = deque([(start, 0)]) # (节点, 距离)
while queue:
node, dist = queue.popleft()
if node == target:
return dist
for neighbor in graph[node]:
if neighbor not in visited:
visited.add(neighbor)
queue.append((neighbor, dist + 1))
return -1 # 不可达
经典题目:
- 200. Number of Islands — 岛屿数量
- 994. Rotting Oranges — 腐烂的橘子
- 752. Open the Lock — 打开转盘锁
- 127. Word Ladder — 单词接龙
模式 6:DFS(深度优先搜索)
核心思路:递归深入探索,遇到死路回溯,适合遍历所有路径。
def dfs(graph, node, visited):
if node in visited:
return
visited.add(node)
# ... process node ...
for neighbor in graph[node]:
dfs(graph, neighbor, visited)
# 带回溯的 DFS(找所有路径)
def dfs_paths(graph, start, end, path=None):
if path is None:
path = []
path = path + [start]
if start == end:
return [path]
paths = []
for neighbor in graph.get(start, []):
if neighbor not in path:
new_paths = dfs_paths(graph, neighbor, end, path)
paths.extend(new_paths)
return paths
经典题目:
- 78. Subsets — 子集
- 46. Permutations — 全排列
- 22. Generate Parentheses — 有效括号
- 17. Letter Combinations of a Phone Number — 电话号码字母组合
模式 7:动态规划(Dynamic Programming)
核心思路:将问题拆成子问题,存储中间结果避免重复计算。
# 0/1 背包问题
def knapsack(weights, values, capacity):
n = len(weights)
# dp[i][w] = 前 i 件物品、容量为 w 时的最大价值
dp = [[0] * (capacity + 1) for _ in range(n + 1)]
for i in range(1, n + 1):
for w in range(capacity + 1):
if weights[i-1] <= w:
dp[i][w] = max(dp[i-1][w],
dp[i-1][w - weights[i-1]] + values[i-1])
else:
dp[i][w] = dp[i-1][w]
return dp[n][capacity]
经典题目:
- 70. Climbing Stairs — 爬楼梯
- 322. Coin Change — 零钱兑换
- 198. House Robber — 打家劫舍
- 300. Longest Increasing Subsequence — 最长递增子序列
- 5. Longest Palindromic Substring — 最长回文子串
- 72. Edit Distance — 编辑距离(Hard)
模式 8:二叉树遍历
核心思路:前序、中序、后序、层序遍历,递归和迭代都要会写。
# 递归三序遍历
def preorder(root):
if not root: return []
return [root.val] + preorder(root.left) + preorder(root.right)
def inorder(root):
if not root: return []
return inorder(root.left) + [root.val] + inorder(root.right)
def postorder(root):
if not root: return []
return postorder(root.left) + postorder(root.right) + [root.val]
# 层序遍历(BFS)
from collections import deque
def level_order(root):
if not root: return []
result = []
queue = deque([root])
while queue:
level = []
for _ in range(len(queue)):
node = queue.popleft()
level.append(node.val)
if node.left: queue.append(node.left)
if node.right: queue.append(node.right)
result.append(level)
return result
经典题目:
- 102. Binary Tree Level Order Traversal — 层序遍历
- 104. Maximum Depth of Binary Tree — 最大深度
- 199. Binary Tree Right Side View — 右视图
- 236. Lowest Common Ancestor of a Binary Tree — 最近公共祖先
模式 9:二分查找(Binary Search)
核心思路:在有序数据中每次排除一半,O(log n) 查找。
# 标准模板(找第一个 >= target 的位置)
def binary_search(nums: list, target: int) -> int:
left, right = 0, len(nums) - 1
while left < right:
mid = (left + right) // 2
if nums[mid] < target:
left = mid + 1
else:
right = mid
return left if nums[left] == target else -1
经典题目:
- 704. Binary Search — 标准二分
- 33. Search in Rotated Sorted Array — 旋转数组搜索
- 153. Find Minimum in Rotated Sorted Array — 旋转数组找最小值
- 4. Median of Two Sorted Arrays — 两个有序数组的中位数(Hard)
模式 10:堆(Heap / Priority Queue)
核心思路:维护 Top K 元素或实时获取最大/最小值。
import heapq
# 找前 K 个最大元素
def top_k(nums: list, k: int) -> list:
return heapq.nlargest(k, nums)
# Top K 频率元素(手写堆)
def topKFrequent(nums: list, k: int) -> list:
freq = {}
for num in nums:
freq[num] = freq.get(num, 0) + 1
heap = [(count, num) for num, count in freq.items()]
heapq.heapify(heap)
return [heapq.heappop(heap)[1] for _ in range(k)]
经典题目:
- 215. Kth Largest Element in an Array — 第 K 大元素
- 347. Top K Frequent Elements — 前 K 个高频元素
- 23. Merge k Sorted Lists — 合并 K 个排序链表
- 621. Task Scheduler — 任务调度器
二、刷题路线图:4 阶段系统训练
根据大量上岸候选人的经验,我总结了一套 4 阶段、8 周 的刷题计划:
阶段 1:Blind 75(2 周)
Blind 75 是最经典的刷题清单,由前 LeetCode 员工 Blind 整理,覆盖面试最高频的 75 道题目。
| 天数 | 目标 | 题目数 |
|---|---|---|
| Day 1-2 | 数组与字符串 | 8-10 道 |
| Day 3-4 | 链表 | 6-8 道 |
| Day 5-6 | 栈与队列 | 5-6 道 |
| Day 7-8 | 树与 BFS/DFS | 10-12 道 |
| Day 9-10 | 哈希表 | 6-8 道 |
| Day 11-12 | 堆 | 5-6 道 |
| Day 13-14 | 动态规划 + 回溯 | 10-12 道 |
关键原则:每道题限时 30 分钟。做不出来就看答案,理解思路后合上答案自己重写一遍。
阶段 2:LeetCode Top 150(2-3 周)
在 Blind 75 基础上扩展到 150 道,覆盖更多变体和 Medium/Hard 题目。
阶段 3:公司高频题(1-2 周)
针对目标公司刷高频题:
| 公司 | 高频题数量 | 特点 |
|---|---|---|
| Meta | ~30 题 | 图 BFS/DFS、动态规划、贪心 |
| ~30 题 | 设计题、优化题、Hard 偏多 | |
| Amazon | ~30 题 | 行为面试 + LC 基础题 |
| Microsoft | ~25 题 | 树、链表、基础算法 |
阶段 4:模拟面试(持续)
- 每天 1-2 道题,限时 30 分钟/题
- 使用 Pramp 或 interviewing.io 进行真人模拟面试
- 录音自己的解题过程,回听改进表达
三、面试实战技巧
技巧 1:拿到题目先别急着写
错误做法:拿到题直接开写代码
正确做法:
- 确认输入输出格式
- 举一个简单例子手动算
- 说出你的思路(面试官想听你思考过程)
- 分析时间/空间复杂度
- 再开始写代码
面试官:"请实现 LRU Cache"
❌ 错误:直接开始写代码
✅ 正确:
"我理解这个需求是设计一个固定容量的缓存,支持 get 和 put 操作,
访问或插入的元素标记为最近使用,容量满时淘汰最久未使用的元素。
我会用哈希表 + 双向链表来实现,get/put 都是 O(1)。
我先确认一下,需要支持删除操作吗?...好的,那我开始写。"
技巧 2:边写边解释
class LRUCache:
def __init__(self, capacity: int):
# 用 OrderedDict 同时保持插入顺序和 O(1) 查找
self.cache = collections.OrderedDict()
self.capacity = capacity
def get(self, key: int) -> int:
if key not in self.cache:
return -1
# 访问后移到末尾(最近使用)
self.cache.move_to_end(key)
return self.cache[key]
def put(self, key: int, value: int) -> None:
if key in self.cache:
# 已存在则更新值并移到末尾
self.cache.move_to_end(key)
self.cache[key] = value
if len(self.cache) > self.capacity:
# 容量满时删除第一个(最久未使用)
self.cache.popitem(last=False)
技巧 3:主动讨论边界条件
写完代码后主动说:
“我考虑了几个边界情况:
- 空输入 → 返回默认值
- 单个元素 → 直接返回
- 所有元素相同 → 退化到 O(n)
- 极大输入 → 我的解法 O(n log n) 应该能处理”
四、避坑指南
坑 1:刷题数量焦虑
误区:别人刷了 500 题,我只刷了 100 题,是不是不够?
真相:面试只考 1-2 道题,关键是你刷的题覆盖了核心模式。Blind 75 + 公司高频题已经足够。
坑 2:只看不写
误区:看题解看懂了 = 自己会写了
真相:看完题解一定要合上答案自己重写一遍。只有写出来的才是你真正掌握的。
坑 3:忽略 Hard 题
误区:面试只考 Easy/Medium,不用刷 Hard
真相:Google 确实会考 Hard。建议至少刷 10-15 道经典 Hard 题,比如:
- 4. Median of Two Sorted Arrays
- 72. Edit Distance
- 212. Word Search II
- 298. Binary Tree Longest Consecutive Sequence
五、推荐资源
| 资源 | 说明 | 链接 |
|---|---|---|
| Blind 75 | 最经典刷题清单 | github.com/leetCodeBlind75 |
| NeetCode 150 | 带视频讲解的 150 题 | neetcode.io |
| 公司高频题 | 按公司分类的高频题 | LeetCode Discuss |
| 算法模板 | 整理好的代码模板 | github.com/gaowenl/leetcodenotes |
面试总结
成功经验
- 模式优先于题目数量:掌握 10 个核心模式 > 刷 500 道随机题
- 限时训练:每道题 30 分钟,模拟真实面试压力
- 错题本:记录做错的题目和原因,定期回顾
- 合上答案重写:看题解后必须自己重写一遍
面试注意事项
时间管理:每道编程题 30-45 分钟,需要合理分配给分析、编码和测试。
沟通表达:边写边解释思路,让面试官跟上你的思考过程。
推荐阅读
- SDE 面试完全指南 — SDE 面试全流程准备策略
- 系统设计面试完全攻略 — 分布式系统设计的核心原则与高频题目
- 行为面试 STAR 故事模板 — Leadership、决策、冲突解决等高频行为问题的回答框架
💡 需要面试辅导?
如果你对准备技术面试感到迷茫,或者想要个性化的面试指导和简历优化,欢迎联系 Interview Coach Pro 获取一对一辅导服务。
👉 联系我们 获取专属面试准备方案