
聊个绕不开的话题刷力扣。很多准备代码面试的人第一反应都是往难题上使劲觉得简单题没技术含量、中等题不过瘾只有把困难题写出来才算有实力。但我在实际准备面试、也陪不少人做模拟面试之后得到的结论恰恰相反简单和中等难度的力扣题才是绝大多数面试机会里的决胜盘。任何一家公司的算法面题目难度基本都集中在这个区间考的就是你把基础数据结构用熟、把常见算法模板内化的能力。这篇文章不搞“七天速成”那种口号只把我验证过的一套完整刷题思路讲清楚。内容围绕简单题和中等题展开包括难度怎么配比、时间怎么分配、做题的完整流程怎么走、中等题里最高频的解题框架有哪些以及一些只有踩过坑才会懂的细节。无论你是刚开始刷题的新手还是刷了几个月总觉得没进步的半熟手应该都能从里面找到可以直接上手的办法。1. 为什么简单题和中等题才是面试决胜盘1.1 简单题的真作用是建立代码手感和边界直觉我刚开始刷题那会儿其实也看不上简单题总觉得自己已经会写业务代码了再去做这种“小学生题目”是在浪费时间。后来帮别人改代码、做模拟面试、自己也反复刷才真正理解简单题的价值根本不在题目本身而在于它能帮你把两样东西练成肌肉记忆代码手感和边界直觉。代码手感听起来很虚实际就是你写代码时不假思索就能写对的部分。数组下标要不要减1、字符串遍历前要不要判空、链表删除头节点时需不需要哑节点、循环条件是小于还是小于等于这些细节如果每次都要临时想一遍你的解题速度会非常慢。而简单题正好是这些基础操作的密集训练场反复做几轮之后你再去做中等题很多细节根本不需要过脑子自然就写对了。边界直觉就更关键了。中等题往往是在简单题的基础上加一个变化而这个变化经常藏在边界条件或者特殊输入里。空数组、空链表、元素全相等、负数、溢出、返回值类型不匹配这些坑没有别的取巧路径只能靠大量简单题把“见到特殊输入就警觉”的习惯练出来。我自己的习惯是每天花10到15分钟做一道简单题热身重点不是通过而是要求自己一次写对、不调试。这种训练坚持一段时间你写中等题的稳定性和速度会明显上一个台阶。1.2 中等题是区分度最强的一档难度如果简单题是在打地基那中等题就是决定你能不能通过面试的那面墙。实际面试里绝大多数算法题都集中在中等难度面试官要考察的不是你有多天才而是你面对一个不算复杂的任务能不能条理清晰地拆解、选型、实现。中等题恰好就是这个能力的度量尺。为什么不是难题因为面试的考核目标是可培养性和工程能力。难题往往需要灵光一闪在短时间内想到一个很不常规的思路这种能力当然有价值但在日常工作中并不常见。中等题不一样它的复杂程度非常接近真实项目里的“有点难的日常任务”你需要理解需求、选择合适的数据结构、权衡时间和空间的取舍再把逻辑用代码实现出来。面试官通过一道中等题就能比较准确地判断出你未来接手一个中等复杂的模块时能不能靠谱地交付。所以中等题才是拉分项。如果只是似懂非懂面试官多追问几个“为什么”就会露馅如果基础模板掌握得很熟中等题往往可以现场拆解从容地给出暴力解法再逐步优化整个思考过程清晰可控。这种表现才是面试官想看到的。1.3 难度配比实操两成简单、六成中等、两成难题我见过不少刷题半年、进度条拉得很长的人最后折在面试上原因不是不够努力而是难度配比出了问题。天天钻难题简单中等不屑一顾结果面试里碰到中等题反而卡壳因为最该熟练的东西没有形成条件反射。我的个人配比是简单题两成、中等题六成、难题两成。刚开始刷题的新手可以把简单题提到三成多给自己一些成就感和缓冲但不要超过三成因为每天的时间是有限的简单题练多了边际收益会下降。中等题必须是最主要的投入它是面试的主战场。至于难题两成足够一道难题花三个小时才搞懂未必比花两个晚上吃透三道中等题更划算毕竟面试里碰到原题或者高度相似题的概率主要集中在简单和中等难度区间。难度配比还要跟着阶段走。第一轮学基础阶段简单题多一些先把数据结构用熟第二轮正式刷题阶段中等题全面铺开追求覆盖面和方法迁移第三轮冲刺阶段再适当引入难题练练压力和思维拓展。每个阶段任务不一样配比也要动态调整这才能叫有策略地刷题。2. 动手刷题之前先把这几件事想清楚2.1 选定主语言别在刷题中途频繁切换语言选择这事很多人不重视但它其实是影响刷题效率最直接的因素。我见过一些开发者今天用 Python 刷、明天切 Java、后天又用 C结果每门语言都是半生不熟的状态库函数要查、语法要试算法思路再好也被这些杂音拖累。正确的做法是选一门主语言练到“不用查文档也能写出来”的程度。字符串切片、数组排序、哈希表增删查改、栈和队列的用法、链表节点的定义这些都必须完全来自你的肌肉记忆。你可以把常用操作整理成一份速查表放在本地编辑器里随时检查但到了刷题后期尤其是模拟面试时要强迫自己不看速查表也能写对。至于要不要学第二门语言作为备用取决于你的时间和目标岗位。如果时间充裕学一门脚本语言做辅助当然可以但必须保证主语言绝对巩固之后再考虑。如果时间紧张就一门语言用到底把模板、边界处理、常见解法全部固化在这一门语言上比贪多要有效得多。2.2 按数据结构和算法分模块扫荡顺序比数量重要刷题最忌讳随机抽题。今天随机抽一道链表明天随机抽一道动态规划知识点被切得零零碎碎你很难在同一段时间里反复接触同一种算法模式迁移效果非常差。更高效的做法是把题库拆成模块按照依赖关系一个一个扫荡。我常用的顺序是这样的数组与字符串、链表、哈希表、栈与队列、双指针、二叉树、递归与回溯、排序与二分查找、动态规划、图论。这个顺序不是随便排的它的逻辑是知识点之间的依赖关系。动态规划需要递归和子问题思维而二叉树的遍历是建立递归感最好的入口图论的深度优先搜索和广度优先搜索本质上又建立在树的遍历之上。跳跃式前进会让自己不断触碰超纲内容浪费时间还打击信心。每个模块内部也有讲究。先做几道简单题把基础模板写熟再做中等题观察题目是如何在基础模板上增加约束和变化的。这个过程很像先学会骑自行车再去练习载人、爬坡、变道。不要把“刷了多少题”当目标把“这个模块的套路是否已经内化”当目标效果会好得多。2.3 每日时间拆解工作日的45分钟该怎么用时间规划这件事直接决定你能不能长期坚持下去。很多人一开始给自己定的目标是每天刷5道题坚持一周就彻底放弃原因不是懒而是计划太不切实际。我推荐一个务实版本工作日每天45到60分钟只完成一道题和这道题的复盘。前15分钟读题、想思路、写伪代码中间15到25分钟写代码并调试最后10到15分钟复盘把解法、复杂度、易错点记录下来。周末再安排一个完整的时间块用来攻克需要长时间思考的中等题以及整理一周的错题和模板。有人会担心每天一道题够不够。实际上只要选题方向正确45分钟一道中等题的节奏坚持三到四个月就能覆盖绝大部分主流题型。更重要的是这种节奏不痛苦、能持续你会更容易坚持到真正见效的节点。刷题是一场长跑而不是冲刺前面跑太快的人往往到不了后程。2.4 代码模板与刷题笔记简单工具带来大提升我不喜欢把刷题工具搞得很复杂但有两样东西确实帮我省了大量时间。第一个是建立自己的代码模板文件把每种数据结构的初始化、常用遍历、常见边界处理保存下来。比如二叉树的递归三要素、链表反转的迭代写法、二分查找的边界模板这些不是题解而是你自己提炼出来的“代码积木”在正式解题时可以直接拼接。第二个是刷题笔记用来记录每天的推导过程和卡点而不是抄题解。笔记里我一般写三件事我的第一思路是什么、卡在哪一步、最终解法为什么这么想。复习的时候你看到的不是一道孤立的题而是自己的一段思考轨迹。这种记录方式比单纯背答案有价值得多因为面试官追问的往往不是“代码怎么写”而是“你当时是怎么想到这个解法的”。3. 一套从新题到复盘完整可复制的刷题流程3.1 新题前25分钟只做三件事拿到一道新题我给自己定过一个“25分钟法则”。前25分钟只做三件事把题目读懂并用样例手工推演一遍把暴力思路说出来哪怕不够好明确这道题的复杂度目标。第一件事很容易被跳过但往往是最重要的。很多时候你觉得自己没思路其实是没真正理解题意。把样例数据手动走一遍输入输出的关系就清楚了解题点也常常在这个过程里浮现出来。第二件事是逼自己先写暴力解法因为它能给你一个正确性已知的参考解。有了参考解后面优化时就有明确的对比目标不会凭空抓瞎。第三件事是根据数据规模预判复杂度比如数据量是10的5次方那 O(n²) 大概率超时应该往 O(n log n) 或者 O(n) 的方向想。这25分钟里必须动手不能盯着题目发呆。哪怕思路是错的也要把第一版伪代码写出来写着写着经常会有新的突破口。25分钟后如果确实没有头绪才可以进入下一步看题解。3.2 看题解的正确姿势先思路后代码很多人的看题解方式是直接滑到代码区看完觉得“哦原来如此”关上页面下次遇到还是不会。这种看题解方式效率极低因为看懂了代码和你能够独立推导出解法是两个完全不同的能力层级。我建议按这个顺序看先看时间空间复杂度要求再看解法的核心思路说明最后才看具体代码。如果核心思路理解了你应该能不看代码就自己把实现写出来。看代码只是为了验证你的理解有没有偏差而不是让你逐行背诵。看完之后还有一个高价值动作把这道题和自己做过的题建立联系。比如这道双指针题和我之前做的那道都是从两端向内收敛这道哈希表的题和另一道题都是空间换时间的思路。这种联系做得越多你的知识结构越牢固。看题解之后也不要急着标记“已掌握”。我会强制自己再做两件事写一遍复杂度分析以及写一句这道题的适用条件。比如“这题可以用双指针因为数组是有序的如果数组无序就未必适用”。这些延伸思考才是题解真正的价值所在。3.3 错题本和间隔复盘法把短期记忆变成条件反射错题本不是简单地记录哪些题没做对而是记录哪种思维模式没建立起来。我的错题本会分成两块左边是题目和我的错误解法简述右边是这个题对应的核心模式和正确思路。复盘时只看右边尝试推导出完整解法推不出来再去看左边的题目。复刷节奏我用的是“2天、7天、30天”三轮法。第一次刷完的第2天复刷一次检验短期记忆第7天再刷看能否独立做出来第30天再刷一次确认是否内化成了长期记忆。三轮都能独立完成这道题才可以移出重点列表。如果某道题反复卡在同一类思维问题上我会直接把它标成重点题每次集中复习时优先处理。这个方法看起来笨但非常有效。因为真正让你通过面试的不是“你曾经会做某道题”而是“你看到某类特征就能自动触发相关解法”。间隔复刷锻炼的就是这种条件反射式的解题能力比临时刷一百道新题更有用。4. 中等题高频模型和解题框架4.1 双指针把 O(n²) 压成 O(n)中等题里出场率最高的解题框架之一就是双指针。它的典型适用场景是有序数组、链表和字符串里需要成对比较或分段处理的问题。核心思想是通过两个指针维护某种单调性把一层嵌套遍历降成一次线性遍历。举个例子一个有序数组和一个目标值要找一对数让它们的和等于目标值。暴力做法是双重循环复杂度 O(n²)。用双指针的话左边指向数组开头右边指向数组末尾如果当前两个数的和小于目标值就把左边指针右移让和变大如果大于目标值就把右边指针左移让和变小相等就直接返回。整个过程每个元素最多被访问一次复杂度是 O(n)。写双指针时最关键的是想清楚三件事指针初始化在哪个位置、指针移动的条件是什么、循环终止条件是什么。我习惯先画一个例子在纸上手动走几轮指针移动然后再写代码。这样写出来的代码出错率会大幅下降。很多新手出错不是不理解双指针而是没有先想清楚这三个问题就直接开始敲代码。4.2 哈希表空间换时间把查找从 O(n) 降到 O(1)哈希表在中等题里同样高频核心价值是能把“查找某个元素是否存在”这类操作从 O(n) 降到 O(1)。很多题第一眼看起来必须嵌套遍历但只要你能识别出其中一层是在做“成员判断”或“计数统计”就可以尝试用哈希表来改写。这种空间换时间的思路在真实工程里太常见了。缓存系统、去重逻辑、索引建设底层都是哈希思想。所以刷题阶段建立起“能少一重循环就少一重循环”的直觉对你读生产代码、系统设计都有帮助。哈希表的坑也不小。一个常见问题是空间占用随数据量上升面试官特别喜欢追问“如果内存受限怎么办”。这时候你需要说出替代方案比如排序后二分查找、位图压缩、分块处理等。能够讨论这些方案的优劣取舍才是中等题考察的真正深度所在也是简单题和中等题的一个重要区别题目不再只看你会不会写而是看你能否权衡各种方案的利弊。4.3 树的遍历从递归到迭代的思维升级二叉树是面试里的常青树几乎每场算法面试都躲不开。简单题往往只要求一种遍历中等题则会把遍历和其他操作组合起来比如层序遍历、根据遍历序还原二叉树、找路径和等等。递归是树问题最自然的解法框架。写递归有固定套路先写终止条件再确定返回值最后写单层递归逻辑。以中序遍历为例终止条件是节点为空返回值是当前子树的中序序列单层逻辑就是“左子树、根节点、右子树”。只要这个框架清晰大部分树的问题都能套进去。但只写递归并不够。我强烈建议把前序、中序、后序的迭代写法也练一遍因为迭代写法需要显式使用栈来模拟递归过程你才能真正理解“调用栈”是怎么展开、又是怎么回溯的。这份理解对后续做深度优先搜索、回溯算法甚至一些需要手动控制遍历顺序的题目都有直接帮助。我辅导别人时发现很多人的递归错误都出在不清楚递归栈的还原顺序而练几道迭代遍历很快就能补上这个短板。4.4 动态规划四步法从暴力递归到状态转移动态规划是中等题里最劝退的模型但也是最值得攻克的部分。我见过太多人一上来就背状态转移方程结果题目稍微变一变就全懵。我的建议是放弃背方程从暴力递归开始。完整步骤是四步第一步用递归描述问题把大问题拆成子问题第二步观察递归函数里哪些参数在变化这些变化参数往往就是状态维度第三步写出递推关系也就是状态转移方程第四步确定初始化和遍历顺序。这套“暴力递归 → 记忆化搜索 → 迭代动态规划”的路径是理解动态规划最可靠的路。练习节奏上先不要追求状态压缩或者高级优化把一维和二维的常规动态规划做熟多覆盖几种模型比如路径计数、子序列、背包、区间规划。每做完一道题多问自己“为什么状态是这一个维度而不是另一个维度”。这个直觉建立起来之后动态规划对你来说就不再是背模板而是一种真正可以现场推导的思维能力。5. 常见问题与踩坑实录这些是实测过的教训5.1 刷了很久没进步先检查这三个原因第一个原因是只刷不总结。每天机械式做题题解看了就关错题从来不看这就像往一个漏水的桶里倒水感觉做了很多但知识没有沉淀成体系。对策很简单也很粗暴每天逼自己写复盘笔记哪怕只有三五句话也要把核心思路、卡点、复杂度写清楚。第二个原因是过度追求难题。难题做出来当然有成就感但如果中等题模板还不稳定就去研究难题相当于还没学会走楼梯就想跑马拉松。面试中出现难题的概率很低中等题没写好的损失远比难题写不出来的损失大。把精力从难题挪回中等题通常能给面试表现带来立竿见影的提升。第三个原因是不重视表达。很多人自己刷题很顺畅一到面试现场就讲不清楚。面试不是纯做题而是要边说边写。所以每道题做完试着用一分钟把题目、解法、复杂度、边界条件讲清楚。讲不清楚的地方恰恰就是你需要重新理解的地方这也是成本最低的自我检验方式。5.2 本地调试没问题线上提交却挂的排查思路这种情况非常普遍我几乎每周都会遇到一次。原因通常集中在四类第一类是空输入和极端输入没处理比如链表为空、数组长度为0、所有元素相同第二类是整数溢出尤其是求和、比较长度时容易踩第三类是数组越界循环边界写成了小于等于第四类是方法签名和返回值类型与题目要求不一致。遇到这类问题我习惯按固定顺序排查先看函数签名和方法名是否完全匹配再看输入规模和数据范围然后自己构造几个特殊样例逐一验证。如果还查不出来就用纸笔把关键循环手动推演一遍不要在代码里盲目加日志。手推一遍往往比加二十行调试代码更快锁定逻辑歧义。5.3 面试场景的专项训练白板感和讲题感最后一个经验单独拿出来说因为你迟早会撞上这个问题。刷题和面试不是等号关系。真实面试中你面对的是空白编辑器或白纸没有调试器没有网络搜索还有人盯着你写。这种压力感不提前模拟再会做题也可能发挥不出五成。我的做法是每周至少安排一次模拟找一道没做过的中等题打开空白编辑器严格限定时间一边写一边大声说出思路。先讲清楚题目边界再讲暴力解法的复杂度然后给优化方案最后写代码并顺手分析复杂度。整个过程就像面试现场一样不给自己留任何依赖工具的余地。练过几轮之后你会发现那些“面试时做不出来”的问题很多不是算法问题而是表达和心态的问题。把这道坎跨过去你的面试状态会上一个新台阶。最后再分享一个小体会很多人觉得刷题是纯粹的脑力劳动其实它也是体力活和习惯训练。每天保持稳定的节奏比偶尔通宵刷几十题有用得多。如果今天的题实在没思路那就放下明天带着“这道题的卡点是什么”回来继续看反而更容易有所突破。简单题和中等题刷扎实了后面所有的面试场景都是水到渠成。