ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

力扣刷题攻略:从题型模板到面试实战的完整路线

力扣刷题攻略:从题型模板到面试实战的完整路线 1. 刷题前想清楚力扣到底在考什么先抛个暴论大多数刷力扣的人一开始就把方向搞错了。顶着“力扣算法题集合”这个标题进来的朋友大概率已经在题海里泡了一阵子或者正准备一头扎进去。你搜“leecode必刷基础算法题”“力扣刷题攻略”这类关键词说明你已经在找“应该刷什么、按什么顺序刷”的答案。但我想先说一句可能不那么顺耳的话如果只是为了“刷够XX题”而刷那你很可能刷了三百题面试还是挂。力扣LeetCode表面上是个算法题库实际考察的是“把模糊需求抽象成数学模型再用代码精确实现”的能力。我做了几年技术面试官见过太多简历上写着“刷过力扣500题”的候选人一到白板写代码就卡在“题目能看懂但不知道该用什么数据结构”这一步。反过来也见过只刷了不到两百题但思路极其清晰的候选人几乎每道题都能从暴力解推导到最优解。所以这个标题背后真正的需求不是“题集合”而是一套“题—题型—方法—应用”的映射系统。你需要先建立一个认知力扣不是题库是一面镜子照出你数据结构、分治思想、动态规划这些底层能力的真实水平。适合读这篇文章的人我默认有三类准备实习或校招的计算机专业学生想转码或想提升代码能力的在职开发者以及单纯想锻炼逻辑思维的非技术人员。前两类占大多数我会尽量用“能直接用”的语言讲少讲理论鸡汤多给可落地的刷题路线和模板。文章里出现的代码以Python为主因为力扣上写Python调试验证最快但涉及思路的部分对其他语言同样适用——Java、Go、C只是语法不同算法思想完全一样。开刷之前你还需要接受一个事实刷题是一个“由慢到快”的过程。第一周可能一天只能啃下一道中等题感觉效率极低但只要你坚持把每道题背后的模板抽出来而不是一题一题孤立地背三四周之后速度会明显上来。我下面讲的就是怎么让这个“慢热期”尽量短。2. 一套可复制的刷题规划方法2.1 核心不是“题量”而是“题型覆盖率”很多人搜“力扣刷题攻略”时其实想找的是一张“必刷题清单”。清单可以给你但在这之前先明白一个更重要的逻辑力扣上有超过三千道题没有任何正常人能全部刷完也不该刷完。面试官也不会因为你刷得多就给你加分他只会看你能不能解决他现场出的那一两道。所以真正要做的是用有限的精力和时间覆盖核心题型。核心题型有哪些按我的经验面试中高频出现的类型就这么几种数组和字符串、哈希表、链表、栈与队列、二叉树、图的基础遍历、二分查找、双指针、滑动窗口、动态规划、回溯、贪心。每一类你需要做到三件事知道这类题的基本模型掌握每种模型常用的数据结构能默写出对应模板的核心代码框架。这三件事都做到了你再去看所谓的“必刷基础算法题”就会觉得那不过是把同一个模板套到不同场景里。我见过太多人刷题时陷入一个误区一道题做不出来就开始翻题解看懂了就标记“已掌握”然后下一道。这种刷法刷两百道和刷二十道没有本质区别因为你脑子里存的不是“方法”而是一堆“单题答案”换个马甲你就不认识了。2.2 三种基础规划路线按你的时间选一条时间比较充裕的在校生建议走“全刷基础路线”按数据结构的章节顺序线性表、栈队列、树、图、排序与查找每学完一块理论就去力扣刷对应标签下的题目。这个路线的缺点是慢优点是扎实适合还在上算法课或者刚开始自学数据结构的同学。时间比较紧的求职者建议走“高频题型路线”直接刷力扣的“面试经典 150 题”和“Top 100 高频题”清单配合自己的薄弱项补充练习。这个路线的关键在于“带脑子刷”——每做一道题强行问自己这道题属于哪个题型我用的算法有没有更优解这个模板还能适配哪些题已经在职、只想保持算法手感的人可以走“每日一题周赛路线”每天固定二十分钟做一道题周末参加一次力扣周赛不用求排名主要是保持思维活跃度。这个路线的重点不是量是连续性和接触新题型的频率。不管你选哪条路我强烈建议你做一个“题单进度表”记录三列题型、题目编号、用的核心模板。别只记录“做完了没有”把模板写下来这才是真正有价值的部分。刷到五十题的时候回头翻这个表你会看到自己的薄弱点集中在哪一类然后有针对性地加练。2.3 每天刷多少、刷多难才最合理这个问题的答案因人而异但有几个原则是通用的。第一不要只刷简单题。简单题的价值在于帮你熟悉API和基本语法刷多了会给你“我好像还行”的错觉。我见过不少人打卡了一百多道简单题一上来就信心满满去面试结果被一道中等难度的二叉树变体直接打懵。第二不要把困难题当主食。困难题往往是多个中等难度的知识点缝合在一起你还没建立基本模板时就硬啃大概率是看题解、抄代码、假装会了整个过程下来收获极少。更合理的比例是简单题占两成中等题占七成困难题占一成——困难题只用于检验自己是不是真的能把几个模板组合运用。第三一天拆成三个短时段效果优于三个小时连刷。早上花十五分钟回忆昨天那道题的核心思路正常刷题一小时晚上睡觉前再花十分钟口述一下今天这道题的解法流程——注意是口述不要看代码说得出来说明你真的理解了。这套方式可能听起来有点麻烦但实际用下来比一次性猛刷三个小时记忆留存率高很多。我个人的实践经验是刷题这件事最忌讳“赶进度”。你今天“刷”了三道题每道都只是看过题解就过和只做了半道但把这一题翻来覆去研究透、把三种解法的复杂度都推了一遍后者对你的提升远大得多。3. 核心题型拆解与代码模板3.1 数组与双指针刷题量最大的基石数组在力扣里无处不在。数组题最简单的做法是暴力二重循环但面试中几乎不会让你就这么过——你至少要把复杂度从 O(n²) 优化到 O(n) 或 O(n log n)这几乎是默认要求。而做到这一步最常用的工具就是双指针。双指针分两种一种是快慢指针常见于链表和数组中的“去重、移动元素”问题另一种是左右相向指针常见于有序数组和字符串的“两数之和、反转区间、回文判断”问题。举个例子力扣第 26 题“删除有序数组中的重复项”初级写法是每次发现重复就移动后面所有元素复杂度 O(n²)。用快慢指针慢指针指向“下一个不重复元素该放的位置”快指针负责扫描整个数组遇到不重复的元素就把它搬到慢指针位置然后慢指针前进一格。代码模板大概是def removeDuplicates(nums): if not nums: return 0 slow 0 for fast in range(1, len(nums)): if nums[fast] ! nums[slow]: slow 1 nums[slow] nums[fast] return slow 1这题的精华不是那段循环而是“slow 维护什么、fast 维护什么”的边界划分。你只要把这两个指针的职责想明白同类的“移动零”“压缩字符串”基本上就是改两行代码的事。左右相向指针的经典应用是判断回文和有序数组找目标值。核心思路左指针初始在最左右指针在最右根据当前两数之和与目标值的大小关系决定移动哪一侧。这种指针的移动逻辑往往伴随一个排序预处理——排序是 O(n log n)后面双指针扫描是 O(n)整体复杂度比暴力 O(n²) 低一个档次。数组题还有一个高频隐藏知识点是“前缀和”。很多题目问“某个区间的和是否满足条件”你如果每次都循环求和那就很慢。前缀和的思路是提前算好从开头到每个位置的总和把区间和转化为两个前缀和相减单次查询 O(1)。遇到子数组、子串求和相关的题目优先考虑前缀和或差分这是经验之谈。3.2 哈希表空间换时间的第一选择哈希表HashMap/HashSet几乎可以说是力扣刷题出场率最高的数据结构因为它能把“查找某个元素是否存在/计数的位置”这一步从 O(n) 降到 O(1)。最经典的场景是“两数之和”。正常人第一反应是两层循环但如果你遍历一遍数组边遍历边把“目标值 - 当前值”记在哈希表里那么后续任意一个数字到来只需查一次哈希表就能知道它有没有对应的另一半。代码极其简洁def twoSum(nums, target): seen {} for i, num in enumerate(nums): complement target - num if complement in seen: return [seen[complement], i] seen[num] i这个模板延伸出来可以解决很多变体三数之和先排序再固定一个数、四数之和、判断是否存在两个数之差为 k、数组中出现次数最多的元素等等核心都是“用哈希记录已经见过的信息”。用哈希表时有一个很容易踩的坑不要把哈希表当作万能药。有些题目用哈希表确实能过但空间复杂度会上去。比如“找出数组中最长的连续序列”你第一反应可能是排序再扫描但这样是 O(n log n)。更优的做法是把所有数字放入哈希表然后只从每个连续序列的起点开始向后查找整体是 O(n)。这道题的精髓在“找出起点”这个动作——如果一个数减一之后仍然存在说明它不是起点直接跳过。这种优化思路光靠背哈希表模板是背不出来的你得真正常见场景推一遍。3.3 链表操作画图永远比脑子想靠谱链表题是面试高频题也是很多人掉线的重灾区。原因很朴素链表的指针操作牵一发动全身你稍微一走神next 指向哪里就很乱。我的建议是拿到链表题先别急着写代码边上有纸就在纸上画两个节点、画箭头把“谁指向谁”理清楚再写。最常见的链表题型是反转链表。迭代版模板如下def reverseList(head): prev None curr head while curr: next_node curr.next curr.next prev prev curr curr next_node return prev这个模板的诀窍是在改变 curr.next 之前一定先用 next_node 把后面的节点保存住否则你就断链了。很多初学者第一次写反转链表都会犯这个错误原因就是没理解“链表中每个节点只有一个 next 指针你先动了它后面的节点就找不到了”。链表题里还有几个高频变体找到链表的中间节点快慢指针快指针一次走两步、慢指针一次走一步、判断链表是否有环同样是快慢指针如果会相遇说明有环、合并两个有序链表用递归或迭代都能做、删除倒数第 N 个节点快指针先走 N 步再和慢指针同时走。你会发现链表题大多是在“快慢指针”“哑节点”“递归”这三个套路里打转并没有太多花哨的算法。这里补充一个重要技巧用虚拟头节点dummy node处理链表操作可以省去大量特判。比如你要删除链表的头节点如果没有 dummy你得单独判断“当前节点是不是头节点”有了 dummy 节点头节点也变成了普通节点代码逻辑就统一了。这个技巧在处理复杂链表插入和删除题时简直救命我强烈建议你养成默认加 dummy 的习惯。3.4 二叉树遍历与递归不会树的算法题寸步难行二叉树是力扣里区分“刷过题”和“真会算法”的分水岭。很多人对树的恐惧其实是对递归的恐惧——不知道递归什么时候该 return什么时候该传值什么时候该收集子树的返回值。树题的核心其实只有一个你要相信自己定义的递归函数。拿最大深度举例你定义函数的意义是“返回以当前节点为根的子树的深度”然后大问题就变成了“左子树的深度和右子树的深度取最大的加一”。写出来特别短def maxDepth(root): if not root: return 0 return max(maxDepth(root.left), maxDepth(root.right)) 1递归题最怕的是你想“一步一步跟着函数走”这是注定跟不下去的。正确姿势是明确三件事递归的终止条件是什么、当前节点要做什么、子问题返回值怎么用。三件事想清楚再复杂的树题也只是在这三个步骤里做变化。树的前中后序遍历用递归写很简单但面试也常考非递归写法用显式栈模拟这个建议也练一练。层序遍历则要用队列做 BFS每次循环处理当前队列长度——注意这个“当前队列长度”要提前存下来因为你处理的过程中队列会不断加入新节点不存下来的话循环次数就会失控。树的题量在力扣里很大我建议优先掌握这些二叉树的最大深度/最小深度、翻转二叉树、对称二叉树、验证二叉搜索树、最近公共祖先、二叉树的直径、路径总和系列。这几类覆盖了“递归终止条件”“左右子树返回值处理”“全局变量更新”三种核心模式吃透它们树题就不会再觉得难了。3.5 动态规划入门先定义好状态再说怎么转移动态规划可能是刷题路上最大的一道坎没别的原因它太抽象了。一个数组、一个二维表格、一个“从前 i 个物品中选”……状态怎么定义边界怎么初始化转移方程怎么推每一步都像是在猜。但我想告诉你一个相对实用的经验先不要一上来就套“最优子结构”“无后效性”这些名词先把问题转化成“从起点到终点的路径选择”。比如爬楼梯问题你站在第 i 层之前是怎么上来的可能是从 i-1 层跨了一步也可能是从 i-2 层跨了两步。那么到第 i 层的方法总数自然就等于到第 i-1 层的方法数加上到第 i-2 层的方法数。这就是状态转移方程dp[i] dp[i-1] dp[i-2] dp[1] 1, dp[2] 2你可以把 dp[i] 理解成“达到这个位置有多少种方案”然后努力把题目里“到达当前位置”的方式枚举出来。这种“最后一步分析法”对入门非常管用。真正难起来的是二维 DP 和背包类问题但底子仍然一样定义 dp[i][j] 的含义再想清楚它可以从哪些前序状态转移而来。刷动态规划题时有一个很常见的困境看题解觉得特别简单自己写就是想不出来。这个真的无解只能靠多练但你可以做一件事降低痛苦——把做过的 DP 题按“状态定义”分类总结比如“一维线性 DP”“二维网格 DP”“背包 DP”“子序列 DP”。每类积累五到十道题你会发现这类题的状态定义方式高度相似有了熟悉感之后就不会畏难了。我提醒一句动态规划题的初始化非常容易出错。dp 数组开多大、dp[0] 或 dp[0][0] 是 0 还是 1、空数组时返回什么都要特别注意。很多时候你感觉转移方程写对了却还是错问题多半出在初始化和边界处理上。3.6 回溯算法的通用框架先选进去再选出来回溯算法题在力扣里有一大类典型代表是排列、组合、子集问题。这类题的代码风格高度统一本质上就是一个“尝试—递归—撤销”的循环。你要做的核心动作就三个把当前选择加入路径递归进入下一层递归返回后把刚才加进去的选择移除撤销。我习惯把它套成一个模板def backtrack(path, options): if 满足结束条件: 记录结果 return for 选择 in options: 做选择加入path backtrack(path, 新的options) 撤销选择从path弹出举个例子生成“1 到 n 中所有长度为 k 的组合”def combine(n, k): res [] def backtrack(start, path): if len(path) k: res.append(path[:]) return for i in range(start, n 1): path.append(i) backtrack(i 1, path) path.pop() backtrack(1, []) return res这个 for 循环里的 start 参数是控制“组合不重复”的关键因为下一层只能从当前数字后面的数字开始选。如果是排列那就不需要 start而是用一个 used 数组记录哪些元素已经用过了。初学者很容易把这两者搞混我的建议是做题时直接问自己同一个元素能不能重复使用不同顺序算不算不同答案这两个问题的答案直接决定了你写的是 used 还是 start。回溯题没有太多奇技淫巧代码模板背熟了剩下的就是练“剪枝”的功力。剪枝的意思是在循环中提前判断某些分支不可能产生有效结果直接跳过从而大幅减少递归次数。典型例子是组合总和问题中“当前和已经超过目标值”的分支。这一招对处理大数据量的回溯题几乎是必须的不加剪枝你很容易在 LeetCode 上看到超时的红字。4. 复杂度和边界面试和竞赛的隐藏扣分点4.1 时间复杂度分析不能只背结论很多人刷题只关心“代码能不能过”从不分析时间复杂度这是很致命的。力扣的判题器会限制运行时间但面试官问复杂度的时候你不能只会说“这是 O(n)”——他下一步一定追问“为什么是 O(n)最坏情况呢空间呢”我的建议是每做完一道题花两分钟把时间复杂度和空间复杂度写下来。写的过程其实就是推演代码的过程你数一下代码里的循环嵌套层数比如一个循环套一个循环就是 O(n²)你用了一个哈希表那空间大概率是 O(n)。这个习惯坚持二十道题你就不会再觉得复杂度分析是什么高深的事了。还有一个常见的坑把递归的复杂度错误地当成 O(n)。递归的复杂度要算“调用次数乘以每次调用的开销”二叉树的递归遍历是 O(n)但如果一个递归函数在每个节点都会展开两个分支总调用次数的量级可能就不是 n 而是 2^n 了。回溯算法动不动指数级复杂度原因就在于递归树的分支特别多。4.2 那些容易让人 TLE 和 MLE 的错误对于大多数算法题TLE超时往往不是力扣系统卡你而是你的算法复杂度本身不够优。一个 n 的规模到 10^5 的题如果你写的是 O(n²) 的双重循环系统肯定让你超时。所以每次看到 TLE 时第一步要做的不是去优化常数项而是想我的算法是不是可以降一档复杂度把 O(n²) 改成 O(n log n)把 O(n log n) 改成 O(n)这才是本质性的解决方式。MLE超内存相对少见但偶尔也会出现在二维 DP 的题目中你开了一个 n×n 的数组n 一大就直接爆内存。这类问题的常规解法是状态压缩——把二维数组缩减成两个一维数组或者只保留上一行的信息空间复杂度就从 O(n²) 降到 O(n)。我做“不同路径 II”这类题时就踩过这个坑改成滚动数组后内存占用和速度都好看很多。另外还要注意 Python 的一个隐藏问题频繁地 append 和 pop 本身是 O(1)但如果你频繁拼接字符串比如在循环里用“”拼接那会让复杂度退化成 O(n²)因为字符串是不可变对象每次拼接都会创建新字符串。有这种场景时用列表收集再用 join 拼接通常是更好的选择。4.3 边界条件自查清单边界条件是“代码看似没毛病但提交错一片”的头号原因。我整理的这份自查清单几乎每次提交前都可以过一遍输入为空时你的代码会走什么分支会不会访问 nums[0] 导致报错输入只有一个元素时你的循环或递归能不能正常工作目标值不存在时你返回的是 -1 还是 None面试中要问清楚返回什么。处理数组下标时有没有出现“越界访问”尤其是 nums[i1] 这类写法循环边界是不是应该写成 range(n-1)整数值会不会溢出在 Java、C 里尤其要注意Python 不用太担心但其他语言要记得用 long 类型。双指针的退出条件是什么是 left right 还是 left right题目要求的是原地修改吗你创建了新数组会被判错——很多数组题明确要求 O(1) 额外空间。递归的终止条件会不会在某些测试用例下永远触发不了比如目标值不存在递归就会一直进行直到栈溢出。你不需要背住这清单只需要每次提交 WA答案错误的时候对照清单检查一遍慢慢就会形成条件反射。实际上水平达到一定程度后大部分人写代码的过程中就会避开这些坑。5. 刷题过程中的常见问题与排查技巧5.1 题目看了没思路怎么办这是所有人都会遇到的情况别慌思路不是靠“想”出来的是靠“套”出来的。我建议按照下面这个顺序来猜第一步看数据范围。n 小于等于 20大概率是回溯或状态压缩n 小于等于 1000O(n²) 能过n 到达 10^5基本可以排除 O(n²)优先想排序、双指针、哈希、二分n 到达 10^6 以上那基本就是 O(n) 甚至 O(n log n) 的线性扫描或哈希表方案。数据范围是题目给你的“提示器”学会看它能看到很多信息。第二步想想题目是不是某个经典问题的变体。两数之和、最长回文子串、最大子序和、编辑距离……这些经典题都有一堆变形你做过的题越多就越能发现“这题我见过类似的”。所以“题目没思路”很多时候不是脑子不行是积累不够。第三步先想暴力解。你不需要一上来就最优解先写一个能得出正确答案的暴力版本然后在此基础上优化有没有重复计算是否可以用哈希表省去扫描是否能排序后用双指针暴力解往最优解优化的路径几乎就是算法题的思考路径。如果这三步都走完了还是没思路那就看题解。看题解不丢人但看的时候带着问题看它用了什么数据结构它的时间复杂度为什么是这个量级它的解法解决了我刚才思考中的哪一步卡点把这些问题想清楚这道题才算真正变成了你的积累。5.2 提交多次不过时的调试思路本地调试是很多新手忽略的技能总以为在编辑器里打个 print 就能找到问题但力扣的代码运行环境跟本地终端有几个不同点。你在本地写代码输出结果和力扣返回结果不一致最常见的三个原因一是力扣的函数签名要求返回值而不是打印输出二是你的代码处理了极端边界但题目要求的行为不一样三是变量作用域或状态在多个测试用例之间残留了比如你使用了类内成员变量而没有重置。我强烈建议的做法是在力扣的“自定义测试用例”里把你怀疑出错的输入单独打进去跑一遍然后看输出。多构造几个边界用例比如空输入、单元素输入、全部相同元素、目标值不存在等情况。如果都没问题但还是 WA那就要回过去重新读题——很多时候不是代码错是题目理解错了。这种情况我见过太多次尤其是一些看似简单的题题目限定条件里藏着“数组已排序”“所有元素互不相同”“只能使用常数级别额外空间”之类的陷阱。5.3 力扣环境下的输入输出与内存细节力扣刷题的标准姿势是只实现核心函数不需要你处理从控制台读入数据的代码。这个机制让刷题体验比 ACM 模式友好得多但也带来一个隐患很多人从来没有写过“如何从一行输入中解析出多个整数”这种代码一到有些考查输入输出的场景就容易发懵。如果将来要参加公司笔试很多公司用的就是 ACM 模式需要自己写输入输出的处理逻辑。建议你提前熟悉一下Python 里读一行整数用list(map(int, input().split()))循环读多行用一个 while 加 try/except 处理结束。Java 里用 BufferedReader 或 ScannerGo 里用 bufio.Scanner。这些不是算法题的核心但笔试中不会写就是会挂。还有一个细节是函数签名。力扣的题解区经常能看到把返回数组改成全局变量、或者把参数改成可变对象来减少传参的写法这种写法在力扣里能过但我个人不推荐养成习惯。它会让代码变得难以分析和复用而且面试时面试官看到这样的代码通常会给负分。5.4 坚持不下去怎么破刷题最难的从来不是某道题而是“连续刷了十几道还是感觉没有长进”的挫败感。我自己也经历过这个阶段后来总结出几个比较有效的调节方法。第一降低单日目标。你不需要每天都刷到三题状态差的时候做一道也不亏关键是“保持每天都在接触”。哪怕只是把昨天那道题重新推导一遍也行连续性和节奏比单日强度重要得多。第二周期性地回头复习旧题。我建议每刷二十道新题就挑五道旧题出来重写一遍重点看当时卡住的地方现在能不能顺利通过。这个动作会让你明显感觉到自己的进步对建立信心很有帮助。第三找到同行的搭子。现在有不少刷题打卡群、学习小组你也可以拉一两个朋友一起互相出题抽查。讲给别人听是最有效的学习方式之一——如果你能把一道题讲得对方听懂了那你自己对这道题的理解大概率已经到位了。第四给自己一个“可衡量的目标”而不是“刷完三百题”这种模糊目标。比如本周内独立做出 14 道中等题、下个月能在一个半小时内完成一场周赛的所有简单题和部分中等题。有明确的目标你才知道自己有没有真的进步。6. 刷完题之后的进阶方向6.1 错题与相似题整理从“做过”到“会做”的桥梁很多人刷题不做整理这是最大的浪费。力扣自带收藏和题解功能但更方便的方式是维护一份自己的笔记文档题号、题目类型、核心思路、最优解法、时间/空间复杂度、你踩的坑各占一行或一个小节。遇到相似的题直接把旧模板拿出来套而不是从零开始想。我个人的习惯是按题型建几个 Markdown 文件比如“双指针.md”“动态规划.md”“回溯.md”。每道题只记一个核心片段思路分析、代码骨架、复杂度以及“我为什么没想出来”的原因。尤其是“为什么没想出来”这部分是我认为最有价值的——大部分题目你忘掉以后重新捡起来只需要看一下当时卡住的原因就能很快回想起来。当你整理到一定数量之后一个明显的变化是看到新题时会自动联想“它和我笔记里的那道题差不多”。这种联想能力就是刷题刷到高阶的标志也是“题感”的来源。6.2 竞赛题、周赛与面试模拟力扣每周的周赛和双周赛是很好的实战训练场。周赛是限时一个半小时的四道题难度从简单到困难递增。我不建议太早参加但当你把基础题型都过了一遍之后周赛能帮你检验两件事一是在时间压力下你还能不能稳定发挥二是你有没有足够快的速度完成前两题。这两件事恰好也是面试笔试中很关键的指标。模拟面试是更有针对性的练习。你可以找朋友互相出题一方扮演面试官要求另一方在白板或在线编辑器里写出完整代码并在写完后口头解释思路和复杂度。很多人在力扣上能刷题但一被问“为什么这么做”就说不清楚这很吃亏。模拟面试练的就是“能写出来也能讲明白”的能力。6.3 从刷题到项目实践的延伸算法题不只是面试题到了这个阶段你会发现一个很自然的趋势刷题中的很多思想其实在真实项目里都在用。哈希表对应缓存与快速查找双指针对应流式数据的窗口处理树遍历对应层级组织结构动态规划对应资源分配优化回溯对应搜索空间的穷举。我印象很深的一个例子是一个做电商朋友在处理库存超卖问题时用的就是“预占库存 最终确认”的两阶段思路这和数据库事务里的两阶段锁没什么关系倒是很像贪心加回退的组合。你说它是不是算法题里的某个模型其实是只不过现实问题披了层业务的外衣。所以不必把刷题看成纯粹的面经准备。当你用算法思维去审视项目中的问题时你会发现自己对很多性能瓶颈有了新的切入点。这也是为什么我和身边的同事都一致认为刷题的终点不是把题目刷完而是把一个“有算法思维的大脑”带进日常开发里。如果你也有这种感觉那么这套方法对你就算真正生效了。
返回列表