1. 力扣刷题的价值与意义
作为一名程序员,我坚持在力扣(LeetCode)上刷题已经三年多了。最初只是为了应付面试,后来发现这种训练对编程能力的提升是全方位的。每天解决1-2道算法题,就像程序员版的"每日俯卧撑",能持续保持思维活跃度。
力扣题库目前有2000+道题目,覆盖了数据结构、算法、数据库、Shell等各个领域。其中算法题占比最大,也是大多数程序员重点练习的部分。这些题目按照难度分为简单、中等和困难三个级别,适合不同水平的开发者循序渐进地提升。
2. 日刷47题的经验分享
2.1 题目选择策略
我通常会采用"主题式刷题法",即在一段时间内集中攻克某一类算法。比如最近两周我专注于动态规划(DP)题目,从简单题开始,逐步过渡到中等难度。47题是一道中等难度的DP题,考察的是"最大子数组和"的变种。
选择题目时我遵循几个原则:
- 先完成同类型简单题,建立基本思路
- 优先选择高频率面试题
- 适当挑战自己,选择一些不熟悉的题型
2.2 解题步骤详解
以47题为例,我的解题过程分为四个阶段:
理解题意:仔细阅读题目描述和示例,确保完全理解要求。这道题需要在给定数组中找到和最大的连续子数组,但有一个特殊条件:允许删除最多一个元素。
基础解法:先不考虑删除元素的条件,写出标准的Kadane算法(时间复杂度O(n))。这是解决最大子数组和的经典算法。
def maxSubArray(nums): max_current = max_global = nums[0] for num in nums[1:]: max_current = max(num, max_current + num) max_global = max(max_global, max_current) return max_global扩展解法:考虑删除一个元素的情况。这里需要维护两个状态数组:
- dp1[i]:以nums[i]结尾的最大子数组和(不删除元素)
- dp2[i]:以nums[i]结尾的最大子数组和(已删除一个元素)
优化实现:将空间复杂度从O(n)优化到O(1),只保留前一个状态的值。
2.3 代码实现
最终优化后的Python解法:
def maxSubArray(nums): if len(nums) == 1: return nums[0] # 初始化状态 dp1 = nums[0] # 不删除元素 dp2 = -float('inf') # 删除一个元素 res = nums[0] for i in range(1, len(nums)): # 更新删除状态:要么之前已经删除过,要么现在删除当前元素 new_dp2 = max(dp1, dp2 + nums[i]) # 更新不删除状态 new_dp1 = max(nums[i], dp1 + nums[i]) res = max(res, new_dp1, new_dp2) dp1, dp2 = new_dp1, new_dp2 return res3. 刷题中的常见问题与解决
3.1 边界条件处理
在实现过程中,有几个边界条件需要特别注意:
- 数组长度为1时的特殊情况
- 全负数数组的情况
- 需要删除的元素是第一个或最后一个的情况
提示:在提交前,务必用这些边界case测试你的代码。
3.2 调试技巧
当代码不能通过所有测试用例时,我通常会:
- 打印中间变量值,观察状态变化
- 用小的测试用例手动模拟算法执行过程
- 对比标准解法,找出差异点
3.3 时间/空间复杂度分析
对于这道题:
- 时间复杂度:O(n),只需遍历数组一次
- 空间复杂度:O(1),只使用了常数个额外变量
4. 刷题的系统性方法
4.1 错题本管理
我维护了一个电子表格记录所有做错的题目,包括:
- 错误原因(边界条件、算法选择错误等)
- 正确解法思路
- 相似题目链接 每月会定期复习这些错题。
4.2 题目分类整理
按照算法类型将做过的题目分类:
- 动态规划
- 双指针
- 回溯
- 图算法等
每个类别建立一个知识卡片,记录核心思想和模板代码。
4.3 刷题节奏控制
我采用"番茄工作法"来刷题:
- 25分钟专注解题
- 5分钟休息
- 每完成4个番茄钟后做15分钟总结
这种节奏既能保持专注,又不会过度疲劳。
5. 进阶学习建议
当你能稳定解决中等难度题目后,可以尝试:
- 参加力扣周赛,体验限时解题的压力
- 尝试用不同语言实现同一道题
- 阅读力扣讨论区的高票解答,学习优化技巧
- 尝试自己出题,这能加深对算法本质的理解
坚持每日刷题的关键是把它变成习惯。我通常在早晨第一件事就是解决一道力扣题,这能帮助我快速进入工作状态。记住,刷题不是为了数量,而是为了培养解决问题的思维方式。