“题海茫茫,leetcode上千道。我该怎么刷题?”
“题目刷完了,面试时手撕代码还是脑袋空空,怎么办?”
你在准备春、秋招面试算法题是不是为这两个问题迷茫过?
那么恭喜你,你发现了这篇宝藏文章。本文将给你指明一条刷题的决胜指南。并从算法的重要性、题库的选择以及刷题的三大步骤分别进行讲解,彻底解决你所有关于面试算法所有的困扰。
温馨提示,本文不会教你如何提升刷题水平,也没有奔着蓝桥杯、ACM等各类算法大赛破纪录的标准冲刺。作者本人就是一个智商平庸的程序员,没有什么说的出口的竞赛经验,上一次刷题还是大一的C语言期末考试……但是面试中算法考核截止上岸前一直保持着100%正确率的光辉记录。
本文的目的纯粹而真实:教你刷最少的题,用最少的时间,最稳妥的方法拿下面试算法题!
如果你的代码能力平平的新手小白,那么这篇文章一定能让你受益匪浅;如果你已经蝉联各种金奖银奖,那就当网络一线牵,相逢即是缘。看在这场缘分上,点个赞再走呗~
好了,废话说到这里。
算法,作为校招乃至社招最重要的考核标准之一,也是考核通过一决生死的关键凭据。是各位候选人准备面试的“重头戏”。
因为算法能力可以看出应聘者的计算机基础能力。这里的基础能力包括:扎实的编程能力、良好的代码习惯以及解决问题的思维能力。
你可能会不屑一顾,算法在实际工作中真的有用吗?
说句实话,非常有用又非常“没用”。
没用在于在你真正入职之后,繁忙的业务和紧促的需求可能让你根本没有时间去思考各种算法如何应用,直接大把大把可复用代码copy;但正因为这些“不经思考”的代码泛滥成灾,一个对于代码严谨性、鲁棒性高标准、严要求的人才就成为了面试官眼里的“香饽饽”。
一个能够挽救这堆“垃圾代码”的人简直就是上帝呀!
所以,算法能力对于长期的需求迭代和工程架构的稳定性而言,是非常非常重要的,也是程序员从普通的搬砖码农晋升到架构师必须具备的能力。
既然它那么重要,作为面试的核心评判标准,不过分吧?
接下来,你可能又好奇了:一恩姐姐,为什么你前面说,这篇文章不能提升算法能力,但能拿下手撕代码呢?
问得好,让我来告诉你们:
首先给各位分享一个宝藏真题网站:https://github.com/afatcoder/LeetcodeTop,github的star已破12k(2022.02),它是我见过的最全面最好用的面试算法真题汇总。
它的题源来自于牛客网面经笔经、CSDN以及热心网友分享,真实可靠,并且实时保持更新,目前共收录了811道真题(仍在持续增长中)。支持按公司、部门、岗位组合查询仓库中的数据,方便大家高效检索,针对性应对面试。
进入首页我们便能看到它按照考察的频度由高到低对算法题进行排序。面试爱考啥一览无余。
通过对这个网站题型的剖析,我们非常清晰地可以总结出以下三条规律:
下面分别详细解释一下这三点:
我做了一个简单的统计,该网站自2020年1月开始统计一共811道算法题,其中数组&哈希表占226道(25.7%),字符串占95道(10.8%),链表占102道(11.6%),二叉树、图占120道(13.6%),栈&队列占84道(9.5),还有一些杂七杂八的数学题和设计题占76道(8.6%)。
这么一算下来已经包揽了互联网80%的题型。而我上述列出来的题型其实都是大家本科时学到的最最基础的数据结构。甚至没有排序算法、BFS/DFS,更别提什么贪心算法动态规划了。
所以,比起去死磕那20%将脑细胞杀光的题型,首先要将这80%的分值稳稳拿到手。等到基础分稳操胜券了,我们便可以去心安理得地锦上添花了。
同样用数据说话,难度题只占103道(11.7%)这说明什么呢?
大厂算法题对题目难度要求不高。面试总共1小时左右时间,算法考查最多也只能占30min左右的时间。对于难度大的题目,大部分候选人基本无法保证在这么短时间内给出一个正确解法。因此较为简单直接的题型成为考核的不二选择。
大家可以观察一下这些高频题目最近考察时间,是不是就是昨天,前天,甚至基本所有题都在一周内被反复考过。这说明啥?说明面试官的题库高度重合且更新频率低!
有一个关系不错的面试官小哥哥跟我说,他这一年面试只考过3道题,翻来覆去反复考。“方便呀”,他懒懒地说,“平时工作那么忙,也没太多时间研究那么多题型。一般会提前花点时间搞透几道经典题型就用上了,等以后有空再换吧。”看起来这个老哥的“有空”是迟迟未到。
所以呢,高频题的生命周期是永久的,是经久不衰的,是反复利用的。这个公司考到的题说不定换一家公司还会考。好好琢磨高频题是一个非常省时省力的小技巧。
说了那么多,帮大家总结一下吧。优先看 高频的、难度中等偏低的、较基础的数据结构的题型。
答应我,这一步先确保做好,完完全全不需要动脑,只需要稍微努力就能成功战胜70%的面试算法。
当然了,也不是说到此为止了。选择了去支持一恩姐姐的你们,智商肯定是胜于常人的(手动狗头)剩余的30%还得是要努努力好好争取的。
下面就来说说具体的刷题方法吧?
现在还在困惑这个问题吗?别愁了,有这个时间我都刷了2道题了。就看三:
资源的位置也贴在上面了,大家在牛客网上都可以直接搜到。我其实非常推崇大家直接用牛客网题库刷题,它的IDE和界面很大程度上还原了真实面试环境。大家提前熟悉一下“考场氛围”对于当天面试的手感和心态都很有帮助~
我刷题的主要输出是剑指Offer,LeetCode和公司真题都是随意打打辅助。对于剑指,我是每一道题都认真刷了至少3遍,刷后仔细总结、举一反三。而LeetCode主要是会针对一些弱点题型进行专项突破,没有去系统地刷。
同时在准备某家公司面试前一周,我会提前三四天每天刷一份该公司的算法真题,主要是用来碰运气,万一这两个面试官正好好兄弟互抄题库呢?
我们分三个阶段一一讲解,分别是:刷题前、刷题时和刷题后;
大家一定要抛弃一个错误观念,刷题绝对不是为了那毫无意义的数目和排名。而是为了去掌握一类题型、去巩固数据结构。因此比起去说“我昨天又刷了10道题”,我更愿意去说“我昨天把双向链表这一类问题搞透了。”
所以在刷题的时候一定要刷经典题,要举一反三,要反复刷,从一类题抽象出共通的解法,才能以不变应万变,这才是刷题的本质,而不是单单为了刷题而刷题。
有了这样一个大方向之后,我们第一步要做的就很明确:分类以及确定优先级。按照数据结构的类别进行分类就好啦,比较现成的分类可以直接按照《剑指Offer》这本书的章节来刷;而优先级则可以根据上面总结出的题型规则进行排序。我做了一个分类大概是:
哈希表与字符串 > 链表 > 二叉树与图 > 二分查找与二叉排序树 > 栈、队列、堆 > 其他(主要是一些数学问题)> 递归、回溯与分治 & 贪心算法 > 搜索 > 复杂数据结构 > 动态规划
刷题我有自己的一套组合拳,现在来给大家拆动作讲解一番。
首先刷题一定是有针对性地刷,看完题目后请各位先来一个灵魂三问:
明确后,就拿出模板直接套。这里的模版是你在刷完题后对这类题型总结的模版,具体的总结方法下面小节会提到。
如果一套命中,那么恭喜你,你总结的模板是通用且合适的;如果发现没有模板或解题思路也不用着急。此时就当作面对一道新的算法题并尝试用自己学过的算法知识解决。
第一次写题不用对解题速度过于苛刻,可以给自己2~3小时时间慢慢摸索最好的方式。
时间一过,无论你有没有解出来,都应该结束这道题了。接下来你要做的就是去看看别人的解法和思路。如果你是在牛客网刷题,可以直接点击左上角的“题解”。
一般点赞最多的是最佳的解法,我们要去看看别人的代码好在哪里,和自己的代码有什么区别。主要是从解题的思路、时间、空间复杂度等角度切入,以及是否能从别人代码中获取一些通用的启发。
站在巨人的肩膀上,才能看得更远。
在吸取他人精华后,需要再刷一遍题。这一遍刷题主要是去证实你是否真正理解并掌握了最佳解法。这一遍成功AC后,你这道题才算是真正的“刷”完。
这一步应该是最关键的一步。
我从学生时代就一直秉承着总结是将知识真正化为己用的最核心的方法。即使到了工作阶段,依然非常受用。
对于面试算法的总结,我会去按题型进行分类,并且对于每一类题型我都会总结出一套伪代码。
每每刷完一题,我便将这道题所总结出的思路归纳到这类题型下:
可能有的人会好奇伪代码怎么写,我这里教大家一个通用的方法:既然不好抽象解法,我们抽象题目。将题目去简化为一个知识点,然后针对这个知识点写算法。
给大家举一个例子:
“滑动窗口算法”类题型可以用于解决最小覆盖子串、找到字符串中所有字母异位词、无重复字符的最长子串类问题。
我总结了一套滑动窗口算法的抽象思想,可以以不变应万变:
int left = 0, right = 0;
while (right < s.size()) {
window.add(s[right]);
right++;
while (valid) {
window.remove(s[left]);
left++;
}
}
总结的思路详细写在这篇文档里,大家速速进来学习一下:https://blog.csdn.net/qq_29966203/article/details/100070662
有时候我会发现自己对于某一类题无法总结出模版,或一直卡壳在一类题时。我就会专门抽出一定的时间专项攻克。这个时候我就会拿出题海战术:LeetCode。因为LeetCode题实在太多了,应有尽有。我会在LeetCode上搜索该类题直接一个猛刷的大操作,相信在千锤百炼后,脑部和手部的记忆也会给你一套自己的方法论。
看到这里,如果你对总结仍然有点云里雾里,不知如何下手。
毕竟宠粉如一恩姐姐为各位上岸可是倾心倾力,操碎了心。
我在总结过程中,按照《剑指Offer》的目录分成了十二类,每一类我都从剑指和LeetCode选择了几道极具有代表性的题型(也可以说是知识点型题)并写出了对应的解法,每道题后面标注了LeetCode/剑指上对应的题号,方便大家查询并自行练习。
家人们,直接冲就完事儿了。
第一章 链表:https://blog.csdn.net/qq_29966203/article/details/100496138
第二章 栈、队列、堆:https://blog.csdn.net/qq_29966203/article/details/100550574
第三章 贪心算法:https://blog.csdn.net/qq_29966203/article/details/94612334
第四章 递归、回溯与分治:https://blog.csdn.net/qq_29966203/article/details/93963493
第五章 二叉树与图:https://blog.csdn.net/qq_29966203/article/details/96424693
第六章 二分查找与二叉排序树:https://blog.csdn.net/qq_29966203/article/details/100169820
第七章 哈希表与字符串:https://blog.csdn.net/qq_29966203/article/details/100029889
第八章 搜索:https://blog.csdn.net/qq_29966203/article/details/100088992
第九章 动态规划:https://blog.csdn.net/qq_29966203/article/details/95489974
第十章 复杂的数据结构
第十一章 其他:https://blog.csdn.net/qq_29966203/article/details/100658666
上面精炼出的约120道左右算法题可谓是题题经典。
每一道题我都刷了至少3~4遍,总结出的模板能让我有十足的底气地应对所有面试题。与此同时,针对临考前这短暂时间如何高速高效抱佛脚,我将上面的算法汇总进一步浓缩再浓缩,总结了一个精简版算法总结与归纳,共50题不到。基本每一次面试前我都会花个大约半小时的时间将里面的算法模型迅速过一下脑子,保持一个代码的手(脑?)感。
目录我就不列出来了,大家点进去看吧。每一道题已经都属于一个核心必考知识点了。
算法总结与归纳
https://blog.csdn.net/qq_29966203/article/details/102745404
以及因为总结出来的题目实在太重要了,于是我又双叒叕将这些算法题打印出来了,每天背一背,快乐养乐多~
我还会在每次面试完后,针对该场面试的手撕代码重新巩固与批注自己的笔记体系。所以打印出来的笔记才会密密麻麻一大片,有的地方记不下了就贴上了便利贴……
还得多说一句,总结真的是一个非常好的学习习惯,他能够将知识真正化为己用,成为自己的东西。各位在看完一恩的资料后,一定要自己总结一份属于自己的资料,归纳出自己的模板。相信拥有一份属于自己的武林秘籍后,无论面对什么样的算法题,都能邪魅狂狷一笑“呵,就这?”
好了,刷题的方法也说的差不多了,最后来一点我在经历过各路面试总结出的一些
面试的手撕代码,相对于你们平时参加各种比赛的算法题,最大的不同在于它要简单太多。很多人认为他难,其实并不是题目难,而是在面试这个一对一的氛围下所营造出的一种紧张、窒息的氛围会让原本你还不错的代码能力大打折扣,很多题。所以一定要保持一颗好的心态,同时要多刷题,尽量用惯性代替脑子。防止出现一些难以应对的意外。
最后如果这篇文章对你有帮助的话,记得点一个赞或收藏~一恩姐姐祝所有点赞的小可爱都能成功上岸哟~