1. 力扣题目100题的价值与意义
刷题是程序员提升算法能力的必经之路,而力扣(LeetCode)作为全球知名的编程题库平台,收录了大量高质量的算法题目。"力扣题目100题"这个标题背后,实际上代表着一个系统性的算法训练计划。对于准备技术面试的程序员来说,这100道题目往往涵盖了数据结构与算法的核心知识点。
我在过去三年里指导过上百名学员的算法训练,发现很多人在刷题时容易陷入两个极端:要么随机刷题缺乏系统性,要么死磕难题忽略基础。精选的100题训练计划恰好能解决这些问题 - 它既保证了知识点的全面覆盖,又控制了合理的训练量。
2. 如何构建有效的100题训练计划
2.1 题目分类与知识点覆盖
一个优秀的100题清单应该包含以下核心数据结构与算法类型:
| 类别 | 建议题量 | 核心知识点 |
|---|---|---|
| 数组与字符串 | 15-20题 | 双指针、滑动窗口、前缀和等 |
| 链表 | 8-10题 | 虚拟头节点、快慢指针、反转等 |
| 二叉树 | 12-15题 | 遍历、递归、Morris遍历等 |
| 动态规划 | 15-20题 | 背包问题、状态转移方程设计等 |
| 回溯算法 | 8-10题 | 排列组合、剪枝优化等 |
| 图论算法 | 10-12题 | DFS/BFS、拓扑排序、最短路径等 |
| 堆与优先队列 | 5-8题 | 堆排序、Top K问题等 |
| 其他高级算法 | 10-15题 | 位运算、数学问题、设计题等 |
2.2 难度梯度设计
合理的难度分布应该是:
- 简单题:30%左右,用于建立信心和巩固基础
- 中等题:50%左右,重点训练和突破
- 难题:20%左右,挑战思维极限
提示:不要一开始就做太多难题,这容易打击信心。建议按照"简单→中等→难题"的顺序循序渐进。
3. 高效刷题的方法论
3.1 五步刷题法
我在实践中总结了一套高效的刷题方法:
理解题意(5-10分钟)
- 仔细阅读题目描述
- 用自己话复述问题
- 确认输入输出格式和边界条件
设计测试用例(5分钟)
- 设计正常情况用例
- 考虑边界条件(空输入、极值等)
- 设计错误输入用例(如果需要)
思考解法(15-30分钟)
- 先想暴力解法
- 尝试优化时间和空间复杂度
- 画图辅助理解(特别是树和图问题)
编写代码(20-40分钟)
- 先写伪代码理清思路
- 注意代码规范和边界处理
- 写完立即用设计的测试用例验证
复盘总结(10-15分钟)
- 记录解题思路和关键点
- 分析时间/空间复杂度
- 思考是否有更优解
3.2 错题本管理
建立错题本是提升刷题效率的关键。我建议使用如下表格管理:
| 题号 | 题目名称 | 错误原因 | 正确解法 | 复习日期1 | 复习日期2 |
|---|---|---|---|---|---|
| 1 | 两数之和 | 边界条件遗漏 | 使用哈希表存储 | 2023-05-01 | 2023-05-08 |
| 15 | 三数之和 | 去重逻辑错误 | 排序+双指针 | 2023-05-03 | 2023-05-10 |
经验:错题至少要复习两次,间隔时间建议为1周和2周,这样记忆最牢固。
4. 经典100题示例与解析
4.1 必刷基础题(前30题)
这部分题目帮助建立算法思维基础:
- 两数之和(哈希表应用)
- 反转链表(指针操作)
- 有效的括号(栈的应用)
- 合并两个有序链表(递归/迭代)
- 最大子数组和(动态规划入门)
- 爬楼梯(经典DP问题)
- 二叉树的中序遍历(递归/迭代)
- 对称二叉树(递归思维)
- 买卖股票的最佳时机(贪心算法)
- LRU缓存(设计题代表)
以"两数之和"为例,深入解析:
def twoSum(nums, target): hashmap = {} for i, num in enumerate(nums): complement = target - num if complement in hashmap: return [hashmap[complement], i] hashmap[num] = i return []关键点:
- 时间复杂度O(n),空间复杂度O(n)
- 利用哈希表实现O(1)时间查询
- 注意返回的是索引而非数值
- 边界情况处理:无解时返回空列表
4.2 进阶提升题(中间50题)
这部分题目培养解决复杂问题的能力:
- 三数之和(双指针+去重)
- 岛屿数量(DFS/BFS应用)
- 课程表(拓扑排序)
- 单词拆分(DP应用)
- 打家劫舍III(树形DP)
- 合并K个升序链表(堆的应用)
- 最长递增子序列(二分优化DP)
- 编辑距离(经典DP问题)
- 接雨水(双指针/单调栈)
- 寻找重复数(快慢指针)
以"三数之和"为例:
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: l += 1 elif s > 0: r -= 1 else: 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 return res注意事项:
- 必须先排序,时间复杂度O(n^2)
- 去重是关键,需要跳过相同的元素
- 双指针移动时要注意边界条件
- 可以提前终止一些不可能的情况
4.3 挑战难题(后20题)
这部分题目锻炼解决非常规问题的能力:
- 正则表达式匹配(DP难题)
- 滑动窗口最大值(单调队列)
- 最小覆盖子串(滑动窗口进阶)
- 二叉树中的最大路径和(递归思维)
- 最长有效括号(栈的巧妙应用)
- 接雨水II(优先队列)
- 戳气球(区间DP)
- 俄罗斯套娃信封问题(二分+DP)
- 数据流的中位数(双堆技巧)
- 天际线问题(扫描线算法)
以"正则表达式匹配"为例:
def isMatch(s: str, p: str) -> bool: m, n = len(s), len(p) dp = [[False] * (n + 1) for _ in range(m + 1)] dp[0][0] = True for j in range(1, n + 1): if p[j - 1] == '*': dp[0][j] = dp[0][j - 2] for i in range(1, m + 1): for j in range(1, n + 1): if p[j - 1] == '.' or p[j - 1] == s[i - 1]: dp[i][j] = dp[i - 1][j - 1] elif p[j - 1] == '*': dp[i][j] = dp[i][j - 2] if p[j - 2] == '.' or p[j - 2] == s[i - 1]: dp[i][j] = dp[i][j] or dp[i - 1][j] return dp[m][n]解题要点:
- 动态规划是解决这类问题的标准方法
- 状态转移方程需要考虑多种情况
- '*'的处理最为复杂,需要分别考虑匹配0次和多次的情况
- 初始化边界条件要小心处理
5. 刷题中的常见问题与解决方案
5.1 时间复杂度过高
典型表现:
- 暴力解法导致超时
- 多重循环没有优化
解决方案:
- 使用哈希表替代线性查找
- 对有序数组考虑二分查找
- 滑动窗口优化双重循环
- 动态规划替代暴力递归
5.2 边界条件错误
常见错误:
- 数组越界
- 空输入处理不当
- 整数溢出
检查清单:
- 数组/字符串操作时检查长度
- 指针移动时检查是否越界
- 除法操作检查分母为零
- 整数运算检查溢出
5.3 递归栈溢出
预防措施:
- 限制递归深度(Python默认1000)
- 考虑改为迭代实现
- 使用尾递归优化(如果语言支持)
- 备忘录技术减少重复计算
5.4 空间复杂度超标
优化方法:
- 原地修改输入数据(如果可以)
- 使用更紧凑的数据结构
- 及时释放不再使用的变量
- 考虑流式处理大数据
6. 刷题进阶建议
6.1 参加编程竞赛
定期参加力扣周赛和双周赛可以:
- 锻炼在压力下解题的能力
- 暴露知识盲区
- 学习其他选手的优秀解法
6.2 参与题目讨论
力扣每道题都有讨论区,可以:
- 学习多种解题思路
- 了解不同语言的实现
- 发现更优的解法
6.3 定期复习
我建议的复习周期:
- 第1次:做完题目当天
- 第2次:3天后
- 第3次:1周后
- 第4次:1月后
6.4 扩展学习资源
推荐几个高质量的学习资源:
- 《算法导论》- 理论基础
- 《编程珠玑》- 算法思维
- 力扣官方题解 - 具体实现
- 算法可视化网站 - 直观理解
经过系统性的100题训练后,你会明显感觉到算法能力的提升。我在教学过程中发现,坚持完成这个计划的学员,在技术面试中的通过率提高了3-5倍。最重要的是培养出解决问题的系统思维,这比单纯记住几个算法模板要有价值得多。