2026/10/9 15:58:29

刷题三年才明白:一套稳定可持续的算法刷题方法论

刷题三年才明白:一套稳定可持续的算法刷题方法论 不知道是不是只有我这样工作几年之后反而比学生时代更在意“刷题”这件事。2026年3月15日这天我照例早起把上周标记的几道LeetCode重刷了一遍顺手把一道卡了半天的OJ题目换了个解法跑通然后坐在电脑前盯着提交记录发了一会儿呆。从开始规律刷题到现在已经跨过三个年头但直到今天我才真正想清楚一件事刷题真正的门槛不是题量而是你有没有一套稳定、可持续、能复盘的刷题方式。这篇文章就是想把这套方式完整写下来——从选平台、定顺序、拆题型到代码习惯、复盘机制——分享给正在刷题或者准备重新捡起来的你。不管你是刚接触算法题的新人还是为面试冲刺的求职者又或者是工作之后想保持代码手感的老兵我希望这篇“刷题攻略”能帮你少走一些弯路。毕竟时间才是最贵的成本与其盲目地刷个两三百题然后发现效果不大不如从一开始就按照正确的方法来。1. 刷题平台怎么选带着什么目标去刷1.1 力扣、OJ系统和其他平台的实际区别很多新手上来就问“力扣刷题攻略是什么”其实第一步不是攻略而是选对地方。市面上的刷题工具有很多但它们的定位和使用场景差异巨大。力扣是目前中文互联网讨论最多、题目解析最全的平台适合深度练习和面试准备。它的题库按照算法专题、难度等级、公司出题频率做了很好的分类每天还有每日一题社区题解覆盖了从暴力解到最优解的完整思路链。如果你只有一个平台的时间选它。OJ系统则更多指高校或者单位内部搭建的在线评测平台。这类平台通常没有题解、没有讨论区、没有“提示”只有冰冷的输入输出。但也正是这种“裸奔”环境逼着你自己推导、自己验证对做题能力的锻炼反而更扎实。如果你的目标不是面试而是真正把算法功底打牢每周至少在OJ上练几道题会很有帮助。我见过太多人只刷力扣依赖题解刷到后面就是背题。这不能说完全无效但对能力的提升收益会递减非常快。我的建议是两条腿走路力扣负责系统性的知识面覆盖OJ负责检验你离开“拐杖”之后会不会做题。1.2 “必刷基础算法题”到底指的是什么回到热词里反复出现的“leecode必刷基础算法题”这其实是一个流传很广的说法——但“必刷”这两个字很容易被误解。基础算法题指的是一类不依赖复杂技巧、仅依靠数据结构基本操作和经典算法思想就能解决的问题。它们通常分布在LeetCode的简单到中等难度区间比如数组类的双指针移动链表的反转与合并哈希表的去重与计数二叉树的递归遍历基础动态规划的斐波那契、爬楼梯、背包问题简单的贪心与二分查找这些题的共同特点是解法相对固定思路清晰不会涉及“非人哉”的数学构造或复杂的树形DP。它们存在的意义不是让你秀操作而是帮你建立对“算法题是什么”的直觉——当你看到题目时能在十秒内判断这是哪个专题、大概用什么思路去解。但我也要泼一盆冷水“必刷”不等于“只刷”。基础题只是地基地基之上你需要逐步进入更复杂的模型否则刷一百道简单题和刷十道简单题的区别并不大。基础题的定位是“让你足够熟悉代码实现”而不是“让你产生刷题成就感”。1.3 定目标你是为了面试、晋升还是为了保持手感刷题之前先问自己一个很现实的问题我刷题是为了什么这个问题直接决定你的刷题范围和投入节奏。如果是为了准备算法面试那么刷题范围要聚焦。面试考的高频专题就那么多数组、链表、二叉树、字符串、哈希、单调栈、BFS/DFS、贪心、动态规划、二分。你需要按照这些专题去刷中等难度的题尤其是“一题多解”的题——面试官很喜欢问“还有没有其他思路”。如果是为了保持职业手感比如日常写业务代码多、算法用得少那刷题就不该追求题量和难度。每周稳定刷三五道简单题保持对边界条件和复杂度的敏感度已经足够。这种状态下刷题更像是一种“代码健身”重在过程而非强度。如果你还在校想通过OJ刷题打编程竞赛或者应付笔试那又是一个完全不同的方向。竞赛题偏重对复杂算法的灵活运用笔试则更注重速度和准确率你需要的是限时训练而不是悠闲地每天一题。总之没有目标的刷题就像没有目的地的远航——你可能刷得很爽但回头一看既没有沉淀出方法体系也没有在关键时刻派上用场。2. 刷题节奏顺序、时间与难度的平衡2.1 按专题刷不要按难度刷这里我想给出一个很重要的结论按难度刷是效率最低的方式。如果你从“简单”开始一题一题往后刷你会遇到一个尴尬的困境简单题覆盖的知识点不连续今天刷双指针明天刷树后天又跳回哈希表。你的脑子一直处于“切换上下文”的状态每道题都要重新进入一种新的思维模式。这会让刷题变得异常疲惫而且知识点之间无法形成串联。更合理的做法是按专题刷。比如这周只做“双指针”那么从简单到中等把所有标志性的双指针题通刷一遍。你会发现它们背后的规律惊人地一致什么时候移动左指针什么时候移动右指针什么时候需要排序前置这些套路会在不断重复中内化成你的条件反射。专题刷法的另一个好处是效率高。同一专题内第二题的思路可以复用第一题的基础第三题又加深一层你的认知是螺旋上升的而不像按难度刷那样每次都要从零开始。按专题刷三十道题的效果可能胜过按难度乱刷一百道。2.2 一道题卡多久就该“放过自己”新手最容易犯的两个错误一个是卡题卡太久一个是看一眼不会就直接看题解。这两个极端都要避免。我自己的经验是分场景的。如果是系统性学习新专题第一遍做的时候允许自己思考十五到二十分钟。超过这个时间思路基本就枯竭了再看下去只会消耗意志力。正确的做法是先看题解看懂思路之后合上题解自己重新实现一遍。注意是“看懂并独立实现”不是“照着抄一遍”——这是完全不同的两件事。但如果是复习已经学过的专题那就应该给自己更严格的时间限制比如十分钟。这个阶段你考的不是“能不能做出来”而是“还能不能第一时间回忆起对应的解法套路”。如果复习的时候也卡了很久说明你并没有真正掌握这个知识点需要回到第一步重新理解。我见过有人一道题死磕两三个小时不放弃最后AC了感动自己然后第二天再做还是不会。这种方式的投入产出比太低了。遇到卡题果断换思路或者看题解把精力留在下一遍的复盘中风险管理上更划算。2.3 每日刷题和周期复盘的时间分配很多博主喜欢喊“每天刷一题一年三百六十五题”。口号很好但执行起来容易变形——有时候忙了一天晚上硬撑着刷一道难题刷到半夜大脑完全麻木第二天又中断然后产生很强的挫败感。我现在的习惯是工作日每天刷一道但难度灵活调节。状态好的时候刷一道中等题状态差的时候刷一道简单题或者直接做每日一题。重点不是“每天必须刷难题”而是“每天保持接触”。这个频率既不会让我有心理压力也能维持对算法的敏感度。周末则完全不同。周六用来做“集中突破”选一个专题连续刷三到四道同类型的题形成肌肉记忆。周日用来“复盘”把这一周写过的题全部翻出来重做错题提炼总结。这比每天多刷一道题有价值得多因为复盘才是让知识从短期记忆进入长期记忆的钥匙。3. 算法基本功基础题型逐个拆解3.1 数组、双指针、滑动窗口高频主力区数组是几乎所有算法题的载体而双指针是数组题里最常用的技法。它的核心思想非常朴素通过维护一头一尾或者一快一慢两个指针将原本需要两层循环的O(n²)问题降维到一遍遍历就解决的O(n)问题。最经典的题目是“两数之和 II - 输入有序数组”当你看到“有序数组”和“寻找两个数”这两个条件时第一个想到的解法就应该是在数组两端放两个指针根据和与目标值的大小关系来移动指针。为什么能这么移动因为数组有序左指针右边的一定更大右指针左边的一定更小。这种“根据单调性消减搜索空间”的直觉值得在一道题里反复体会。滑动窗口本质上是双指针的一个变体常用于解决“连续子串/子数组”类问题。它的核心在于维护窗口的语义有时候窗口代表“不满足条件的最短区间”有时候代表“满足条件的最长区间”你需要根据题目要求调整两个边界指针的移动时机。刷这类题时的注意事项先确认数组是否有序再确认是否需要排序前置。很多双指针题的第一步是排序如果你忘了这个前提后面的指针移动逻辑全是错的。3.2 链表和快慢指针指针操作的边界感链表的题是笔试和面试的重灾区不是因为难而是因为太容易在“边界条件”上出错。比如删除一个节点时你不仅需要处理当前节点的next指向还需要考虑头节点是否会被删除也就是是否需要dummyHead虚拟头结点。这个小技巧可以帮你省掉一半的边界判断。快慢指针在链表题里扮演的角色很有意思。比如判断链表是否有环一个走一步、一个走两步如果两者相遇就说明有环找链表的中点快指针到末尾时慢指针刚好在中点找倒数第k个节点先让快指针走k步然后两者同时前进。这几种场景用到的都是同一个思想利用速度差制造位置差从而在一次遍历中完成两件事。链表题给新手的建议是不要只是在脑子里模拟动手画图。每条指针变化都用笔画一次画着画着你就会发现自己的认知盲区。我到现在遇到稍微复杂一点的链表题还是会在草稿纸上画图这不是基础差而是严谨的工程习惯。3.3 哈希表用空间换时间的万能辅助哈希表大概是单题出场率最高的数据结构。判断重复、计数、找索引、映射关系——这些需求背后全是哈希表的影子。一个很有代表性的例子是“字母异位词分组”。如果不用哈希表做分类你怎么判断两个单词是不是由同一组字母构成手工比对当然是可行的但时间复杂度感人而且代码冗长。用哈希表的思路是把每个单词排序后的结果当作key把原单词加入对应的列表。这一步操作就直接把问题的复杂度从“两两比对”降到了“一次遍历”。另一个典型场景是“两数之和”的进阶版如果数组无序且需要返回下标那么一次遍历加哈希表记录已经见过的数字就是最优解。这个解法之所以成立是因为哈希表的查询是O(1)的你记住“已经见过的”再回头找“我需要的另一半”比暴力嵌套循环快出一个量级。哈希表本身实现难度不高所以刷这类题的重心反而不在于哈希表而在于你什么时候能想到它。遇到问题先问自己“这题需不需要记录历史信息如果记录的话以什么作为键、什么作为值”能问出这两个问题你就已经领先很多人了。3.4 二叉树和递归建立“栈式思考”的抽象能力二叉树是很多人的分水岭也是面试题的中坚力量。它的核心不是二叉树的“形状”而是递归。几乎80%的二叉树题目都可以用递归解决区别只在于你是“先处理自己再处理子树”前序遍历还是“先处理子树再处理自己”后序遍历又或者是两者之间中序遍历。为什么递归适合树因为树本身就是递归定义的——一棵树的子树还是树。这给了我们底气只要写出一个节点的处理逻辑然后相信递归函数能处理好它的左右子树整个问题就解决了。初次接触的人会觉得这个“相信”很奇怪但这就是递归的精髓——你只需要保证单层逻辑正确并设置好递归终止条件。二叉树题目比较多变但基础就那么几类求最大深度的“后续遍历”判断是否对称以及相同的“同步遍历两棵树”路径总和类的“数值传递与回溯”遍历序列构造树的“前序中序切分数组”。把这些母题搞透你会发现树题其实是在同一个骨架上换不同的皮。给新手的实操建议二叉树题一定要自己动手模拟递归栈。递归不是玄学它在计算机里真实存在是层层压栈再弹栈的过程。你模拟过几个递归栈之后对递归的恐惧感就会转化成掌控感。3.5 递归、回溯、DFS/BFS搜索类题目的三兄弟这三个概念经常被放在一起但很多人分不清。以我的经验来看可以这样理解递归是“实现手段”回溯和DFS/BFS是“搜索策略”。回溯通常配合DFS使用核心在于“状态还原”——一条路走不通时撤销选择回到上一个岔路口。刷回溯题有一个经典模板画出递归树然后套用“选择-递归-撤销”三步法。以全排列为例你的选择列表是“还没有被选过的数字”递归进去之后用标记数组标记某个数字已被使用回溯阶段再把它撤销。这个模板看似机械但覆盖了绝大多数回溯题的骨架。BFS和DFS则负责处理“遍历图/树的所有节点”类问题。DFS用栈隐式的递归栈或显式栈特点是“一条道走到黑”BFS用队列特点是“逐层扩散”。两者没有绝对的孰优孰劣取决于题目场景。比如求“最短步数”BFS通常更自然因为第一次到达目标节点时的层数就是最优解。搜索类题目是很好的“思维训练场”刷完它们你会明显感到自己分析问题的方式变清晰了先拆解问题结构再选择合适的搜索策略最后用递归或队列完成实现。这种能力不只是刷题有用。3.6 贪心、二分、动态规划从直觉到模式匹配这三个专题属于思维含量更高的部分很多初学者在这一带受挫我想拆开说。贪心的难点在于“怎么证明局部最优就是全局最优”。它不像搜索有明确的状态空间也不像DP有明显的递推式。它更像是一种“感觉证明”的组合。感觉来源于你刷过的同类题而证明则需要你学会“交换论证”和“反证法”。哪怕是资深选手面对陌生的贪心题也可能会栽跟头所以这类题不必强求每道都做出来能做出来的是赚到做不出来就把它当作“见识新套路”的机会。二分的难点在边界。很多人写二分时总是想不清楚“left和right什么时候取等、什么时候mid1、什么情况下rightmid”。我的经验是统一用“闭区间”思路来写令left为“可能的最小位置”right为“可能的最大位置”循环条件是left right关键是找准check函数的单调性。只要你能把题目转化成“在有序序列上找一个分界点”剩下只是模板的机械训练。动态规划则是被讨论最多的专题它对新手极不友好。我的建议是不要从复杂状态开始先爬楼梯和斐波那契再背包问题然后是最长递增子序列和编辑距离。DP的核心不是写出转移方程而是先定义好dp[i/j]这个状态到底代表什么含义。状态定义错误后面的转移怎么写都是错的。状态定义对了转移方程往往水到渠成。4. 代码细节与调试习惯刷题质量的分水岭4.1 先把时间和空间复杂度估算出来再动键盘我见过太多的刷题新手——拿到一道题脑子里刚有个模糊的想法就扑到键盘上开始写写完发现超时或者内存爆了再推倒重来。这个过程不仅浪费时间还容易把心态搞崩。正确的顺序是读题 - 分析数据规模 - 估算复杂度上界 - 确定算法方向 - 写代码。数据规模是最好的提示数组长度是10⁵级说明O(n²)基本不可能通过你应该考虑O(n log n)或者O(n)如果数组长度只有不到100那么O(n²)甚至O(n³)都是允许的反而可以放心采用更暴力的解法。刷题到了一定阶段看到题目的第一眼就能估算出目标复杂度这是一种非常重要的“题感”。它可以帮你过滤掉大部分不靠谱的初始思路节省大量无效编码时间。所以请从小题做起养成“动手前先预算”的习惯。4.2 边界条件出现频率最高的翻车点如果把所有提交失败的测试案例放在一起统计边界条件绝对排在第一位。数组为空、数组长度为一、链表中只有一个节点、目标值刚好在区间端点、整数溢出——这些“特殊值”是你写代码时最容易忽略的地方。我的建议是形成一套自己的“边界检查清单”每写完一道题就对照检查一遍输入为空或者大小为1时代码是否仍能工作循环终止条件是否会漏掉最后一个元素指针移动时是不是可能越界整数运算是否可能在极端情况下溢出如果题目数字含负数我的逻辑是否仍然成立这套清单看似琐碎但它的价值在于帮你建立自动化检查的反射。我第一次在面试中因为漏掉空数组检查而翻车以后就再也没忘记过这个习惯。4.3 调试技巧print大法之外的选择刷题场景下的调试和真实工程项目调试不太一样你可能没有IDE里的断点工具也无法依赖日志框架但有一些技巧非常实用小数据量的手算模拟永远是最快的确认方式。拿一组极小的测试数据在脑海里把自己的代码一行一行执行一遍看变量如何变化。这个过程听上去笨但往往能快速定位到逻辑断裂的地方。如果手算太麻烦可以在代码里插入临时的print输出观察关键变量的中间状态——尤其是在循环里打印每次迭代之后的left和right指针位置、或者回溯时的路径数组。这种“最土”的调试方式在任何场景下都好用千万不要觉得低级。还有一种情况是“我的思路明明正确但就是WA”。这时候不要盲目修改而是找几组随机数据用暴力解法写一个比对程序把两种结果不一致的测试样本打印出来。这种“对拍”的思路在竞赛刷题里很常用也是排查隐藏错误的一把利器。4.4 代码风格与写题习惯稳定压倒一切刷题不是写业务代码你不需要过度设计模式但也绝不能写得乱七八糟。所谓“稳定的代码风格”指的是变量命名有含义、逻辑结构清晰、每一步都能讲得出为什么。例如循环不变量——在写循环之前你要清楚“这个循环的每一次迭代开始之前我的左右指针分别代表什么”。把循环不变量写在注释旁边不仅方便自己检查也是面试中展示思维的加分项。还有一点很关键尽量减少代码里的“魔法数字”直接用语义清楚的变量名来表达。刷题圈常说的“可读性第一优化第二”就是这个意思。4.5 一次能AC不是终点多解比较与复杂度优化很多人把“一次通过”当成刷题的高光时刻很高兴地进入下一题。但我想强调一道题“能过”和“吃透”之间还有很大距离。每做完一道题给自己一个“多解思考”的动作除了我提交的这版解法还有没有其他思路比如两数之和暴力法是O(n²)哈希表和排序双指针都能到O(n log n)以内的复杂度但它们的适用条件不同——哈希表需要O(n)空间排序双指针则改变了元素顺序。当你想过这些问题之后这道题才真正属于你。它不是一个孤立的AC而是在你脑中种下了关于时间-空间权衡、数据结构选择的多维度理解。刷题数量不能说明什么但你对每一道题的理解深度会在日积月累中拉开人与人的差距。5. 复盘闭环让刷过的题真正长在身上5.1 错题本不是抄题而是要记录“思维差”说到复盘最笨但也最有效的方法是错题本。但多数人的错题本只是把题目和标准答案抄了一遍除了安慰自己“我有在整理”其实毫无用处。真正的错题本应该记录“我原本是怎么想的为什么错了正确的思路和我的思路差在哪里”。这个“思维差”才是错题本最核心的价值。举个例子我做一道“求最多能容纳水的容器”的题时一开始想到的是暴力枚举左右边界后来才发现应该用双指针收缩为什么收缩因为底部宽度减小的情况下面积只可能变大当且仅当短边升高。这个“意识到移动较矮一侧”的过程才是值得写进错题本的宝贵素材。我把错题本按专题分类每道错题包含五个要素题目链接或描述、提交失败的原因、卡住的关键点、突破思路、同类型题的相似之处。每周末翻一遍一个月后你会发现很多错误是重复在同一个思维盲区里的。5.2 重刷周期新题要刷旧题更要刷很多人刷题数量看起来很多但从不回头重刷。到了面试前发现自己做过的题大多都忘了。这是必然的——遗忘是大脑的正常机制不重刷一定会忘。我的经验是给自己定三个重刷周期三天后重刷一次确保短期记忆变中期、两周后重刷一次确保进入长期记忆、一个月后再看一次巩固体系。每个周期重刷时不会做的题要重新标记为“未掌握”进入下一轮循环。有些题目第一遍看题解会了第二遍独立做出来了第三遍就可以试着用不同的解法做或者把实现时间压到十分钟以内。这种递进式的重刷才让一道题的价值被彻底榨干。所以我不建议追求“刷得多”更看重“每一题都经历了多轮反复”。5.3 如何科学地衡量自己的刷题进步用什么指标衡量刷题进步我见过有人看AC数量有人看提交通过率还有人看连续打卡天数。这些指标都有参考价值但它们都是过程指标不是结果指标。真正有意义的结果指标有三个。第一个是拿到新题时的第一反应速度看到题目之后你能不能快速判断出它属于哪个专题、可能的解法方向是什么。第二个是同类型题目的迁移能力做过一道“岛屿数量”之后遇到“被围绕的区域”你能否快速意识到它们都是DFS/BFS连通分量问题。第三个是写代码的一次通过率也就是你的代码在逻辑、边界、细节上是否足够少出错。这三个指标每两周自测一次即可找几道没做过的中等题限时来做看第一反应和迁移水平再统计一下近两周的提交状态里首次AC的比例。进步不是一条直线很多时候会有一个平台期但只要这三个指标在缓慢上升你就是在真正变强。最后说一点我这两天心烦时想的题外话。刷题这件事有时候真的很孤独——你一个人在编辑器里面对一个又一个判断类、循环类、边界类的问题没有队友会搭把手。但反过来想这种孤独恰恰是自我对话的机会。2026年3月15日这一天我把上个月的错题翻出来重做发现其中一道曾经的“拦路虎”竟然十分钟内就AC了。那个瞬间的爽感比坐在那里空想“我要进步”要实在得多。如果你也在刷题路上别急着追求数量的飞涨先建立专题体系把时间投给复盘和重刷再加上一点点耐心你要的进步自然会来。