每个时代,都不会亏待会学习的人。

大家好,我是 yes。

我持续在 LeetCode 刷算法题将近有一年半的时间了,这一年半以来我对算法的看法改变了很多,但是实话实说支持我前进的还是面试。

在之前的文章提到过我是面试驱动型选手,我享受面试官问我啥我都嘴角一翘微微一笑的那种不羁,而近年来算法在面试中的比重越来越大,所以我花了很大的精力去攻克算法这道难关,确实有点难

我不是天赋型选手,甚至觉得自己有点蠢,在刷题的过程中经常被各种打击,最夸张的就是同一道题刷了 4 次,过一段时间去写还是不会,从下面的这些草稿可以看出我当时内心的那种崩溃。

当然还有给自己加油打气的(不要嫌弃我的字丑哈)。

经过了三本书的系统学习、一年半的刷题,三篇专栏的多次学习,搞了很多大厂的真题练习,基本上有点稳了。

这篇文章想分享一下我面向面试学习算法的一些心得,所以算法大牛、算法爱好者可以关闭这个页面了,这是一篇面向一般程序员的算法面试攻略。

在去年我还参加一个话题回答,「数据结构与算法的学习中,面对经典代码是选择自己实现还是背诵?」,一不小心就被选上中奖了,嘿嘿。本来还想把奖品搞个抽奖送出去的,但是这个包装被我扔了,因为两张算法大地图需要长筒来装,不好运输,之后再看看吧。

来看看我是怎么回答这个问题的吧。

数据结构与算法的学习中,面对经典代码是选择自己实现还是背诵?

我觉得学习算法就是理解+持续练习+刻意的背诵(有选择性的背诵)

有些人学习算法可能是兴趣爱好啥的,很直白的说我就是功利性的学习,并且能够因为功利心而持续学习。

因为功利我想快速得到收益的最大化,但是欲速则不达,因此我会在功利的情况下理性的学习算法。

1、首先巩固基础,万丈高楼平地起。算法就是使用各种数据结构按照一定的流程运行,管你五花八门稀奇古怪的算法题都逃脱不了数组和链表。在数组和链表之上特殊功能化了很多有特殊意义的数据结构:队列,栈等。

数据结构都是因为不同的场景有不同的需求而演化而来,因此在某个场景数组更合适,某个场景链表更合适,你所需要知道的就是它们分别的优缺点和使用的场景,并能知其然而知其所以然。

例如数组下标访问高效,是因为内存连续,因此对 CPU 缓存亲和性更高等。这样使用才能游刃有余,有的放矢。

2、持续练习,光说不练假把式,单单看是没用的,不上手便成空

我没那算法的天赋,在我认为我对基本数据结构有了一定的了解的情况下,看到有些算法题还是蒙圈,没那思路,脑袋空空,那也只能练呗。

遇到完全没思路的题目最多 5 分钟我就会去找题解,有可能 2 分钟,因为功利嘛,还有一部分我觉得我没那脑子我认清自己哈哈哈。

但是在找题解的时候我是秉着一个必须充分理解的目的去的,不理解不放弃,开玩笑答案至少我还是得看懂吧(这句话我现在收回,当时还是太年轻)。

当然这里的不放弃不是指这半天或者一天内一定要搞定。有时候就会陷入瓶颈,隔一天,或者去玩一下回来就会豁然开朗。

通过持续的练习,你脑子里就会渐渐的了解这些题目的套路,你也能更好的关联各种数据结构,这就是感觉来了,你会发现自己变聪明了,这就是要进入良性循环了,并且持续的练习,你会发现某一天如果你没写算法题的时候会有一种罪恶感!

还有我不会借助 IDE 写,就在 LeetCode 上直接写,一个一个自己敲,时刻为着以后面试写题作准备,没错就是这么功利

3、刻意的背诵(有选择性的背诵)

有人会说算法是要理解的,死记硬背是没用的。没错理解是肯定要理解的,死记硬背肯定过两天就会忘了。

但是我认为单单理解还是不够的,理解+练习是可以让你做出题目,但是做不到让你不假思索的做出题目,在面试的这种紧张的情况下,只有类似肌肉记忆才能给面试官最强烈的打击,稍微的紧张可能就会导致连环出错,满盘皆输!

因此对于那些经典的代码,常用的例如二分查找,快排等我都会刻意的背诵,达到听到二分查找,脑子里就有那么些代码出现的程度,没错我还是这么的功利。

也就是说平时刷的算法题都要理解,但是一些经典的代码我认为理解还不够,需要背诵形成肌肉记忆。

有些人可能会觉得,没啥好背的啊,多多练习就会了,额其实多多练习就等于背,是吧你说你写个十几遍不就等于背么。只是我是刻意的背。


啧啧,我觉得我说的真好,哈哈哈。

再补充一下这个回答的个别观点:

1、掌握好基础,也就是那些常用的数据结构和算法,比如队列、栈、堆、归排、快排、二分、动态规划等等,熟悉这些经典数据结构和算法,通透的得知他们的适用场景。

解题无非就是将它们套上去,绝对不会叫你创新,你所做的就是套模板,就看你模板选的对不对,套的熟不熟罢了。

2、持续练习,这玩意是最重要的。因为叫很多人看东西没问题,让他上手就会有拖延症,感觉有点麻烦。

但是算法就是得练,没有什么其他选择,不用耍啥小聪明,除非你过目不忘

因为它的解题思路不太符合正常人的思考,所以你需要持续的练习,让你的思维转变过来,形成看到这类的题目就会有应激反应。

还有两点很关键,我强调一下:

  • 不要花太多时间在一道题上,几分钟没思路就看题解,看了题解再进行理解和默写。
  • 不要用 IDE 写,面试的时候就是没联想提示的,有时候甚至是手写,所以在平时就要做好准备,不打无准备之仗。

上面其实讲的就是平日学习和刷题的套路,接下来讲讲如何上手。

上手攻略

我选择小争哥的《数据结构与算法之美》专栏,这个专栏我刷了两遍,虽说我还看了别的专栏,但是这个够了,上手绝佳,贴个专栏的图吧。几乎涵盖了所有的数据结构和算法书籍涉及到的知识点

我就是看这个入门的,基本的套路讲解的很全,推荐先把专栏全面的看一遍,把每节课涉及的到代码自己敲一遍

可以按以下学习顺序、难易程度和重点程度来学习这个专栏。

然后再二刷,二刷的目的是提炼和总结,我来贴一下我之前的个别章节总结,这是之前参加算法打卡活动留下的。

刷完之后,一些经典数据结构和算法至少都认识,也说得上来,基本上算是入门了。

然后再去看《算法(第4版)》这本书,虽说我看了三本算法书但是我觉得这本够了。

一般而言大家都会先推荐书,毕竟书都比较全也更加系统,但是我喜欢反其道而行之。

因为书太厚了,厚就容易劝退,特别是在你对一个领域不太熟悉的时候。

所以我更喜欢先去学别人提炼过的付费专栏,提炼出来的都是重点,让我对核心知识脉络有了充分的认识之后,再去看书来查漏补缺,建立完善的体系

因为在你已经了解大致核心知识点后,你再去看大头书就会有一种熟悉感和共鸣感,这种感觉可以让你把书从头看到尾。

至于为什么看了专栏之后还得看书,是因为专栏毕竟是被人提炼过的,而书的知识点大多都是完整的,你先吸收别人提炼过的知识点,带着别人的想法再去系统的学习,从其中再糅合出自己的总结,这样东西才真的是你的

系统的学习完这本书之后,感觉自己好像很厉害了?

并不是。

你还需要去实战,碰一碰真正的面试题,纸上学来终觉浅

当然我是在一开始就刷题了,并不是等专栏、书都看完了才上手,我建议在刷专栏期间就去刷题练练手。

我是在 2016 年才知道 LeetCode 这个网站的,当时我看到同项目组的研究生在刷,他在国外读研,他说这玩意是必须刷的。

那时候还没中文版,全英文的我看着很高级就上去玩一玩,不怕各位笑话,第一题就不会,只能写出暴力解法,循环两个数相加之和来对比。

看了题解之后恍然大悟,暗骂自己好蠢,然后继续往后刷了几题成功被劝退,然后就没有然后了...

到现在 LeetCode 上的题也越来越多了,按顺序刷就太"蠢"了,根本就没必要全刷,要刷经典题,归类刷,把一类题型刷出感觉来才罢休。

一般经典的常见的类型无非是 BFS、DFS、双指针、前缀、背包、二分、链表、二叉树、滑动窗口、堆(Top K)、栈、动态规划、回溯、滑动窗口、位运算、图、各种排序等等。

其实还有一些数学类型的题目,我选择放弃,哈哈哈。

正常情况下面试也不会问数学类型的,至于上述所说的题型,已经有一份很 nice 的算法笔记帮你总结了,很完备,很贴心,1730 页,20W 字,汇总了各大题型,基本上每题都附上了各大佬们的高质量解题思路,并附上链接,方便查看原文,我随便截几张图给大家看看。

这个算法汇总是我向鲂姐讨来的,一位刷题找工作的研三党,鲂姐之后打算提供一些关于学习,简历修改,求职路线的1v1辅导服务,敬请期待~

这份总结 PDF 请拉到文末获取。

解题技巧

我再来提一个我个人认为很重要的解题技巧:主干先行再填充细节。这个编码技巧其实不仅仅关乎算法,平日的代码也建议按这个思路写。

我举冒泡排序这个很简单的例子来解释一下这句话的意思。

箭头指向的其实就是交换两个位置内容的代码,可以封装一下,变成下面这样。

这个例子的代码太简单了所以不封装也没事,不过我想提的就是这种封装的思想。

一般而言面试官可以在线实时看到你的编码,他看的不仅仅是你的题解,还包括你的代码风格,排版等等,这也是很关键的一部分。

所以碰到是一些代码比较多的题目时候,注意方法的封装,不要一大坨都写在一起

主干先行的意思是,例如上面的 swap 方法的实现先不要写,你当自己已经实现了 swap 方法来用就行,这就是先完善主干,清晰思路。 这样的代码看起来就不会凌乱,你自己调理也比较清晰。

等主干写完了之后,再去实现你封装的方法,也就是填充细节

当然有人是一坨写完了,然后再进行重构,但是我觉得重构是重构,和我说的这种编码技巧不是一个方向。

我要表达的点是在编写代码的时候展示清晰的思路,并且对你个人而言这种做法也更简单,不会让一些细节干扰你的主线。

可能就冒泡排序而言太简单的,感受不太深刻,大家可以在平时刷题时候练练,相信你能体会到这种做法的好处。

最后

可能大家也看过很多学习算法的分享,很多本书、很多网站、很多课程,多并不一定是好事

我个人认为一个专栏、一个网站、一本书、一份算法笔记对于我这种后端程序员来说足以,不要想着这个课好像不错,这个书好像很多人推,我可以很负责的告诉你,就我提到的这几个你吃透了,你基本上是「化神期」修士了。

还有上面的提到的鲂姐的算法笔记,后台回复「123」即可领取。


我是 yes,从一点点到亿点点,我们下篇见

这份算法攻略,我拿到了5个大厂的offer的更多相关文章

  1. 微信"流量红包"的玩法攻略 广东移动用户有福啦

    前面我们说了广东移动联合微信正式推出流量红包业务,移动终于hold不住了,想要借此挽回一些些损失.只可惜,现在只是广东小范围测试,其他地区的用户暂时还没有这等福利.那么微信"流量红包&quo ...

  2. Delphi NativeXml用法攻略

    NativeXml用法攻略 NativeXml可以在官网上下载,下载后将文件夹放在指定地方,打开DELPHI在其环境变量中引用NativeXml路径,然后在程序中引用NativeXml单元,我们就可以 ...

  3. 德州扑克AK打法攻略

    AK是所有德扑网游中最受争议的底牌,也是一副令人又爱又恨的底牌.<德州扑克培训大师>根据国内德州扑克网游特性,为大家制作了第一套AK打法攻略,希望所有玩家从今天开始能正确认识AK,发挥AK ...

  4. 微信小程序开发公测,小程序账号申请办法攻略

    11月3号晚上 10 点,微信公众平台发布公告,宣布微信小程序正式开放公测.此次小程序公测允许开发者将产品提交至微信公众平台审核,但是暂时不支持发布,也就是说普通消费者若想体验小程序,还需要等待一段时 ...

  5. Delphi NativeXml用法攻略 转

    NativeXml可以在官网上下载,下载后将文件夹放在指定地方,打开DELPHI在其环境变量中引用NativeXml路径,然后在程序中引用NativeXml单元,我们就可以使用NativeXml了. ...

  6. 凭这份pdf让我轻松拿下了蚂蚁金服、字节跳动、小米等大厂的offer

    关于程序员,除了做项目来提高自身的技术之外,还有一种提升自己的专业技能就是:多!看!书! 小编整理出一篇Java进阶架构师之路的核心知识,同时也是面试时面试官必问的知识点,篇章也是包括了很多知识点,其 ...

  7. 攻略三战的完美体验3Castle Fantisia阿兰·梅希亚战争艾伦西战记它包含重做版本(这是新的艾伦·梅希亚大战)

    (城堡幻想曲3,纠正大家个错误哦,不是圣魔大战3,圣魔大战是城堡幻想曲2,圣魔大战不是个系列,艾伦西亚战记==艾伦希亚战记,一个游戏日文名:タイトル キャッスルファンタジア -エレンシア戦記-リニュー ...

  8. 完美攻略心得之圣魔大战3(Castle Fantisia)艾伦希亚战记(艾伦西亚战记)包含重做版(即新艾伦希亚战记)

    (城堡幻想曲3,纠正大家个错误哦,不是圣魔大战3,圣魔大战是城堡幻想曲2,圣魔大战不是个系列,艾伦西亚战记==艾伦希亚战记,一个游戏日文名:タイトル キャッスルファンタジア -エレンシア戦記-リニュー ...

  9. 普通程序员转型AI免费教程整合,零基础也可自学

    普通程序员转型AI免费教程整合,零基础也可自学 本文告诉通过什么样的顺序进行学习以及在哪儿可以找到他们.可以通过自学的方式掌握机器学习科学家的基础技能,并在论文.工作甚至日常生活中快速应用. 可以先看 ...

随机推荐

  1. JVM运行时数据区--本地方法栈

    本地方法栈 1.Java虚拟机栈用于管理Java方法的调用,而本地方法栈用于管理本地方法(一般非Java实现的方法)的调用 2.本地方法栈,也是线程私有的. 3.允许被实现成固定或者是可动态拓展的内存 ...

  2. 【Flutter 实战】文件系统目录

    老孟导读:Flutter 中获取文件路径,我们都知道使用 path_provider,但对其目录对含义不是很清楚,此文介绍 Android.iOS 系统的文件目录,不同场景下建议使用的目录. 不同的平 ...

  3. CSS、bootstrap4等相关疑难杂症

    说明 本篇博客仅用于个人随笔,所以内容比较随意. 在bootstrap4中,引入样式后,按钮.输入框等组件的选取状态会出现黑色加重边框,该如何解决? 解决示例: input:focus{outline ...

  4. 必须了解的mysql三大日志-binlog、redo log和undo log

    日志是 mysql 数据库的重要组成部分,记录着数据库运行期间各种状态信息.mysql日志主要包括错误日志.查询日志.慢查询日志.事务日志.二进制日志几大类.作为开发,我们重点需要关注的是二进制日志( ...

  5. vue中axios的使用

    新开了一个vue项目,从头到尾都是一个人做的,所以就自己配置了一个axios.js文件 第一种方法.使用axios 需要下载安装   npm install axios,下载完成之后 在main.js ...

  6. php第五天-正则表达式,字符串的匹配与查找函数,数组切割

    在php中有两套正则表达式,两者功能相似,一套是由PCRE,使用"preg_"为前缀命名的函数,一套是由POSIX拓展提供的,使用以"ereg_"命名的函数 0 ...

  7. Shell学习(三)Shell参数传递

    一.传参实例 ##脚本文件内容 #执行的文件名 echo $0; #第一个参数 echo $1; #第二个参数 echo $2; #第三个参数 echo $3; ##调用语句 ./testShell. ...

  8. 理解 JAVABEAN EJB POJO

    <Spring实战>第一章:基本理念.各类名称熟语 POJO(Plain Ordinary Java Object)简单的Java对象,实际就是普通JavaBeans,是为了避免和EJB混 ...

  9. 吴恩达Machine Learning学习笔记(四)--BP神经网络

    解决复杂非线性问题 BP神经网络 模型表示 theta->weights sigmoid->activation function input_layer->hidden_layer ...

  10. Vue学习笔记使用系列一【表单】

    脚手架的搭建,请查看另外一篇日记:https://www.cnblogs.com/Fengge518/p/11837078.html 1:直接代码了 1 <!DOCTYPE html> 2 ...