33

不懂算法,还想进大厂?做梦吧

 4 years ago
source link: https://www.tuicool.com/articles/YFJ3Inr
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

大飞。十年互联网人,资深架构师,技术leader。

yAVb6nq.jpg!web

题目有点标题党了,还请大家见谅。下面切入正题。

算法很重要,但算法也是学起来最难,最令人生畏的。

这篇就来说说算法刷题方面的一些经验和技巧。

大家在刷题的时候不知道有没有遇到以下情况。

拿到题目后就开始想着怎么写代码,结果写了大半天,发现越写越乱,最后就写不下去了,又或者是,看到题目后,一脸懵逼,完全不知道怎么下手。

其实,学算法,刷题蛮干是不行的,需要遵循科学的方法。

以下的经验技巧,对于算法新手,或大学没有搞过ACM,想利用业余时间提升算法能力的同学比较有帮助,对于算法高手和ACM大牛,可能不太适用,仅供参考。

算法不是拼智商

算法不是纯粹拼智商的,智商高,就一定很厉害,不够聪明,就一定不行。算法是一种技能,是可以通过科学合理的方式训练出来的能力。

智商的高低,当然会有影响,但这个先天因素无法改变,而科学合理的方法是大家都可以掌握的。

所以,首要的一点,是要意识到,算法不是只拼智商的,也是可以经由后天训练习得的。

难度要循序渐进

有些同学喜欢上来就是干,上来就是终极难度的题目,觉得自己只要做出最难的,其它的就迎刃而解了。这种急于求成的思想要不得。

算法训练是一个系统工程,需要循序渐进,太过于急功近利,反而容易因做不出难题而产生挫败感,带来反效果。

记得我有一个同事就做了次类似的事情。我们当时刚听说有leetcode,就想上去试试,他上去后就挑了一道困难里面还属于比较难的题目,结果想了大半天也没做出来,搞到自己特别沮丧。

你会发现这种做法效率很低,那道题目就算被做出来了,也不代表就可以解出其它的题目。

合理的做法是循序渐进。

如果你本身有基础,熟练度高,那你刷简单的leetcode应该是几分钟一题,几分钟一题的,花不了你多少时间。

如果你刷简单都花费很长时间,说明熟练度不够,就更应该从简单开始。

然后过度到中等,再过度到困难。

这里有个经验之谈。

目前国内大厂的算法考察,基本不会超过leetcode 中等难度,上限难度基本都是leetcode 中等题里面的中等难度(有点拗口,leetcode 中等难度里面也有分档次)。

如果你能够再20分钟内,做出这种难度的题目,国内大厂的算法面试,基本可以畅通无阻。

按算法分类来选题

选择题目,除了在难度上要循序渐进,还建议在算法上进行划分。

基本的算法数据结构是有限的。比如说链表,二叉树,二分查找,动态规划,哈希表。。。

我喜欢按算法的分类来选题和刷题,比如一个时间段,只刷链表题,待刷得差不多的时候,接下来再刷二叉树的题。。。

这种做法可以极大的提高刷题的速度,而且能带来更好的效果。

一,持续地刷同个类型的题目,可以不断地巩固和加深理解。

二,可以更全面地接触这个数据结构,算法的各个变种,这会促使你对这个数据结构,算法的理解更加全面和深刻,学习的效率会更高。

所以在一段时间内,持续地刷特定类别的题目,可以带来事半功倍的效果。

当然,在能力已经比较强的时候,可以采用打散的方式来刷题,可以更好地锻炼思维的灵活性和应变能力,但初期或能力较弱的时候,按分类选题,是比较好的。

解题三部曲

在具体做题的时候,可以采用以下三个步骤来进行。

拿到题目后,不要立马开干,想着下面的三个步骤,一步一步地来。

1. 看懂题目

看懂题目。有的题目很直接,直接告诉你要解决的问题是什么,题目本身甚至都包含了对应的数据结构和需要用到的算法;有的题目很隐晦,看了半天不知道它到底要解决什么问题,可以用什么算法和数据结构来解。所以,看到题目后,一定要先确保自己理解清楚了。

我的一个经验是,拿到一个题目后,看5分钟,如果5分钟之内看不懂,我就mark 下来,留到后面再做,要不很影响刷题的心情。

不过就leetcode 来说,这样的题目不多。基本都能在再5分钟内看懂。

2.分析,推导解法

分析推导题目的解法。

这个步骤要有意识地单独拎出来,不要跟编码步骤混淆在一起。也就是说,你在分析推导题目解法的时候,不要去想任何实现相关地事情,不用去想代码怎么写,不用去想要用什么库,定义什么变量,用多少层循环,都不要想,就想着在逻辑上,这道题目要怎么解。

这样做可以极大地降低你的心智负担,使你高效地想出题目的解法。对于如何将想法变成代码,可以留在下一个步骤,单独来进行。

3.将思路转换为代码

当你确定题目都已经理解,并且分析推导出了题目的解法后,你才开始来思考如何将自己的思路转换成代码。是地,将思路转换成代码,可以是一个单独地步骤,在实际工作中,其实也是很重要的一个能力。

有时,将一个思路转换成算法是很容易且自然的;但有时,有些思路转换成代码,是很有难度的事情。

或者你有体会,分析推导只用了不到十分钟,结果代码写了半小时还写不完整。

怎么定义变量,保存状态,用递归,还是用循环加辅助数据结构等等,都是将思路转换成代码要做的事情。

这个能力也需要刻意地去练习。

算法的封装

接下来,说点更细节的东西,算法的封装。

软件设计里面,最关键的思想就是抽象和封装了。

其实解题也可以用到这种思路。

比如一道题目的正确解法是先排序,再进行二分查找,那你的脑子里面只要记得,快速排序和二分查找,就可以了,不需要去想,快速排序和二分查找的具体实现。

就像我们在写代码的时候,遇到排序,查找,我们一般都直接使用了现成的函数库,而不需要自己动手再写一遍。这个是代码层面封装带来的好处,思维层面的封装也是一样的道理。

这种封装思想在做题的时候可以极大地减轻我们的心智负担,使得自己的脑力可以发挥在问题的核心点上。

用封装的思维去解题,你的解题能力会有快速地提升。

封装的思想可以用于 “ 2.分析,推导解法”  的过程,在 “ 3.将思路转换为代码”  的过程,更是可以用语言内置的算法函数,数据结构来直接实现,也使得从思路转换到代码的过程更加的直观和自然。

在实际的面试或比赛中,除非有特殊说明,一般都可以放心地使用语言的内置算法和数据结构。

然后你可能会问,对于像排序,查找这些基础的算法应该怎么对待呢?我的建议是可以把它们当作重要算法来刻意练习。

快排,快搜,堆排序等,我们可以称它们为元算法。

对于这些算法的刻意练习。一开始的时候,要看算法书的描述,确保自己理解了算法的思路,然后尝试自己实现一遍。

实在写不出来,就参照或者直接抄。一个算法花几天的时间,大部分人都是可以理解并自己实现出来的。(排除一些特别难的,需要更长的时间)。

保持持续的动力

算法能力的提升,是一个长期的事情,需要持续地学习和做题,而刷题又是个比较枯燥的过程,在遇到难题的时候,很容易产生挫败感,甚至导致直接放弃。

所以这里需要特别关注刷题时的正反馈。如果你老是无法解出某个难度或某个类别的题目的时候,你就要考虑降低难度,或者安排额外的时间,去更全面的复习特定的算法和数据结构了。

注意不要死磕!算法学习,特别讲求方法和技巧,死磕非但磕不过去,还可能留下对算法的心里阴影,导致学习障碍。

总结

首先算法不是只拼智商的,是可以通过后天的刻意练习掌握的一种能力。

刚上手的时候,难度上需要循序渐进,最好能够按算法分类来刷题。

解题的时候,建议按这三个步骤来 

1,看懂题目

2,分析,推导解法 

3,将思路转换为代码。

在更细节方面,封装的思想也可使用在算法上面,可以极大地降低我们的心智负担,提升解题的效率。

最后是要注意做题过程中的正反馈,确保自己能持续地做下去。

华丽的分割线

----------------------------------------------------------------------

如果对算法感兴趣的可以看看人魔七七的系列,后面会出一本这个系列的电子书,并且做了一个专门的app来阅读:

https://github.com/renmoqiqi/100-Days-Of-iOS-DataStructure-Algorithm


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK