Skip to content

刷题方法

统计信息:字数 8291 阅读17分钟

作为 LeetCode 的铁粉并受益的刷题人,我认为掌握一套高效的刷题方法尤其有效,否则很难覆盖日益增多的题库,并且大多数时候刷完不久就会忘掉。所以我把当年刷题的经验分享给你,希望我的方法也对你有用,希望我们能做同事。

我方法的核心实际上和背英语单词类似,总结题型,找到高频题并且不断重复。具体来讲就是

按 tag 分类——艾宾浩斯记忆曲线,不断重复刷过的题——不断总结掌握情况

为什么这么来操作是因为经过很多面试后,发现大多数题型还是比较基本和重要的,分布在 medium 和 advanced medium 之间。而这些题目又可以演变出来很多不同的题,但万变不离其宗,抓住本质并且熟练掌握即可。

1 按 tag 分类

第一件事就是按照 tag 把题目分成不同的 list,一般每个公司为一个 list。一定要根据自己的刷题掌握情况来定制 list,这也是我这个方法保证对你有用的精髓。随便从其他地方的舶来品基本没用,因为只有自己才最了解自己的复习情况。如果你基础比较差,之前没怎么刷过题或者是转专业,我推荐的做法是额外分一个 basic list,意思是所有基础的数据结构/算法都覆盖一遍,这些题是一定要会的,基础中的基础。我把我认为基础的 list 需要 cover 的内容分享在这里(后面是题号):

深度优先遍历、回溯算法、动态规划、广度优先遍历、分治算法、贪心算法、滑动窗口、图、树、二分搜索。这个基础的 list 基本上一定要涵盖这些基础知识点(面试必考)。

分类刷题,确保基础的知识点不遗漏

DFS + memo 322
Backtracking 22
DP (DP <--> DFS + memo) 55
BFS 286
PartitionDivide and Conquer 86
Greedy 421
Sliding Window 15
Graph 207 743
Tree
Binary Search

2 艾宾浩斯记忆曲线,不断重复刷过的题

第二步就是著名的艾宾浩斯记忆曲线的运用了。考过托福/雅思的细心的同学可能发现了,这个实际上和记忆英语单词有异曲同工之处 -- 先做 list,第二步我们要干嘛?按 list 不断复习,每天循环呀!这里我用我的 Basic List 来举个例子:

请注意观察我的 Legend

一般表格的第一栏是留给 Legend 的,每次刷完我会记录当前的状态,方便日后巩固。

如果是一次过的:就是直接 y;

如果中途有停顿,而且思路也不清晰的,写 ?;

如果怎么想也做不出来,看了答案的或做之前看过答案,就是 ※。

然后根据这些记录的情况,第二天来安排不同的优先级和精力重新刷这些题,大家可以看到 168 我打了三个 ※,说明 3 次都不会,日后还需要继续巩固此类题型。对于那些 y 的题目直接过,基本上半年再来 review 一次。

每一个题目做标记(类似面试题)Y N ?三种。然后确保自己的答案是正确的答案。如果答案不正确,记住错误的答案,完全没有效果。第二天做的事情不是继续刷新的题目,而是复习旧的知识点。

3 不断总结掌握情况

最后一步也是最重要的一步:总结。我们需要随时记录下当前刷题的状态,然后每天在刷题时做到有的放矢:不浪费每一道新题,不重复任何一道已掌握的旧题。

总结需要注意的关键点:

总结 tag -- 这题我有哪些方法,哪个是最优解 总结笔记 -- 有必要的话需要记下来哪里有这题的笔记 总结相似题型 总结关键解题步骤

总结 tag 大致意思是说:这题大概有哪些方法可以搞定,以及自己最喜欢的方法。一般推荐两种方法即可:基本的 brute force(暴力算法) + advanced algorithm / data structure。注意这两个都是必要的,我有经历过背下来高级解法,结果基本解法不熟练最后被挂掉的面试。大家可能要问:看讨论区那些 ACM 大神们的奇技淫巧太 NB 了,我是不是要全背下来?我的建议是大可不必,记住一个自己最顺手的即可。而且注意:brute force 一定要熟练,在这个基础之上才能开始研究高级一些的解法。

总结笔记,很多的题做了好多遍也不太会,例如我上面的 31,感觉要刷死人了还是不会。那没有办法,我只能把这个解法单独拿出来,写到纸质的笔记本上,有空就看一遍,推一遍,敲一遍。

总结类似题型,这个也很有用,因为往往类似题型都有一致的解法,只是越往难,越是在基础解法上糅合了其他的算法技巧。有时候 LeetCode 上给的类似题型不准,我一般是参考之后再看看大家的建议,然后把所有的先总结出来,并且把相似的题链接起来。每次练习一起练,找出每种题型的基本差异。例如经典的买股票四连问题,建议大家试试看。

总结关键解题步骤。这一点很有意思,主要是说在遇到难题时,看完大神的解法之后自己总结出几点关键步骤,这样下次要是再卡壳了就可以直接看这个,想想之前自己是怎么解的思路,而不是再去看其他讨论。这样循环往复个 2-3 次就能熟练记下来。例如 42 那题,我就写了一个简单的小提示,确保下次再卡壳可以看这个 tips 而不是翻看答案,从头再来推一边。从而提高刷题效率。

按照这个方法不断练习,我保证你最差可以刷进 flag,因为不管是从以前别人面试我的经历还是现在我面试别人的经历来看,大家最看重的其实还是基础算法知识是否牢固,即 medium 和 advanced medium 能否够对答入流

至于那些脑经急转弯式的 easy 和有很多高级技巧的 hard,实际上我个人感觉不是主要的考察范围。除非是 ACM 参赛者,对于一般的 candidate 编程实际上就是一份工作,既然是这样,那就找到合适的方法来应对。把更多的时间花在更宝贵的事情上,例如你喜欢的人和物上。

通过刷题,拿了很多公司(IBM, Google, Amazon, Microsoft, Zenefits, Splunk)的面试以及offer。这428题不是简单的刷一遍就过去的,而是反复练习,直到代码最优,解法最优(有时候甚至觉得自己的代码精简到一个符号都无法减少的地步)。所以有时候面试官问问题,问题还没说完,我就知道应该如何表述自己的心路历程,然后慢慢地给出最优解。

而这一切的关键就在于:做笔记!笔记就记录在源代码中

下面是我的笔记截图:

对于遇到的每个题目,事后我都做上标记:普通题目,难题、好题。此外,每个题目都分为以下几个步骤做好详细的笔记:

\1. 原题目

\2. 自己的第一遍解法

\3. 网上好的解法

\4. 自己可以改进的地方

\5. 进一步精简优化自己的代码直至代码简无可简这是非常关键的一步,到达这一步,才会发现获得能力的提升远远要超过简单地把题目解出来)不一定是代码量最少,而是代码最好(算法,可读性等)

\6. 获得的思考(或者学习到的地方,可以是算法、数据结构或者Java的特性—例如Stream等等)

每一个题目都经过至少一遍这样的迭代。这样几遍下来,我对于每个题目都有了更加深刻的理解,大部分的题目我都有自信能够写出最优解甚至代码都是最优化的(至少比论坛回复里面的最高票答案还要精简)。

总之,不断地学习别人的代码,改进自己的代码,不断地锤炼自己的代码,直至算法最优化,代码最简洁!潜移默化中,不仅对题目解法有了更深刻的理解(什么是最优解),而且也知道如何用最简洁的代码实现这个最优解。

我本人不是算法高手,算是勤能补拙类型。这样长期坚持下来,慢慢地感觉自己编程能力提升了很多。不仅面试的时候得心应手,而且在工作中提交code review的时候,往往有自信说自己的代码是简单,干净与优雅的。


Last update: November 9, 2024