欢迎关注更多精彩
本人是国内互联网的一位普通工程师。我没有参加过学校的集训,没参加过什么大学生acm比赛,也没有报过班,之前在leetcode上周赛最好成绩是53名,hihocoder上也有比较不错的成绩,如下图所示。
我写这文章的目是想告诉大家算法没有想象中的那么难,方法得当学起来挺有趣,对自己能力提升有帮助,对以后的工作也有非常大的帮助。
在我看来,我们做题的目无非是2种,一种是要去打比赛的,一种是希望找工作,或者学习一些算法知识以便后续辅助对计算机知识的深入学习。对于前者本来自认为才疏学浅,不足以论述。今天我就以一个码农的身份来谈谈后者。下面我就以四个方面来讲述。
本部分主要介绍面试时做题的意义
先给出我的观点一道题是一个缩小版的项目。
公司招人是干嘛的,当然是进来做项目的。
那么一个项目从产品到最后产出的过程有哪些(以下是简略版本,实际还要复杂一些)。
看上面的6步跟我们面试算法题过程是一一对应的:
从上面的类比看出,一个做题的过程与做项目的过程高度相似,所以做题可以比较全面的考查求职者的职业素养。那么面试官到底在考查什么呢。
还是从上面6步来分析
总结一下,要考查的方面有:
下面是我模拟一下算法面试经过,来感受一下上面一些能力及考查点在过程中的体现。
以leetcode [0047] 全排列 II 这题为例
面试官:我们先来做个题吧。
我:好的。
面试官:我们先来做个题吧。
我:好的。
面试官:给你一个数组,打印出所有的全排列。
此时,面试官已给出题目(需求),然后你拿到需求,不是马上开始做,而是应该是进入到需求评审(题目中有不清楚的,不合理的都要提出来),这一步就是考查你的业务理解,需求洞察,发现问题的能力。那么我发现了几个问题,1 数组的长度是多少呢,很长的话计算机(单机)也不能做啊,可能要选择多机的方案。数组里数字的大小范围啊,确定了才知道是用什么类型存呢。数组里有没有重复的数字,如果有的话,结果重复的要不要呢。结果要不要以某种顺序排序啊。当然还有其他问题,都要问出来。面试中说话才体现出你的想法。这些问题搞清楚了,算法出来的结果才是面试官想要的。
面试官:数组的话就是长度为1到10吧,然后数字都32位正整数,数字有重复,重复的结果都要出来,不要求排序。
好了下面开始设计(方案设计),
我开始思考(内心独白):这个题之前遇到过,用深搜逐位确定就可以,现在的话用原来的可以搞出来。
我:我有思路了。
面试官:那你讲一下吧。
我:巴拉巴拉…
面试官:这个思路可以,那能把代码写一下么。
我:可以。
写代码ing。。。(代码实现)
我:写好了。
面试官:嗯,我看看。
。。。
面试官:嗯,这个代码没有问题,现在希望结果不重复,你有什么好方法么。(验收提问,考查应变创新能力)
想一会儿。
我:我想到2种方法,一种是把所有的求出来后,再去重,另一种是在搜索中就把重复的去掉了,由于后一种效率更高,我使用后者(比较取舍)。前一种也是有应用场景的。巴拉巴拉。。。
面试官:好的,那你写一下代码。
我:好的。
。。。。
面试官:好的,那我们下一题吧。
以上是一个面试题的过程,基本上是这样。
从上面的过程中可以看考查得非常仔细,从需求评审到方案设计,再到方案取舍,提出问题和挑战。全面的考查了求职者的主观能动性,思考能力,创新能力,代码能力。
好了,讲了这么多,主要是让大家明白,面试官为什么要让我们做题,以及做题中要考查的方面。
那么我们已知道要考查的方面了,怎么样去通过学习提高呢。请看方法篇。
本篇主要讲如何针对上面要考查的方面进行提高。
通过上面的分析,我们知道我们要学习掌握的能力或知识有:
以上5点从1到4是逐级提高的,上下之是相互服务的,缺一不可,第五点是贯穿全局。
对题目的思考过程可以参考一下这一篇文章,先感受一下大致的流程。
leetcode-1674-使数组互补的最少操作次数-线段树
leetcode - 1681 - 最小不兼容性 - bitset -搜索 - 剪枝 - 数字集合
这2题是我在遇到自己不会或者一下子想不出来时所经历的过程,面试时有些时候一下子想不出来也是差不多这么个过程。你思考的都要说出来,让面试官知道,可以相互讨论的。
我一开始也和很多人一样,来一题做一题。做一题,下一题又不会了。感觉进度很慢,而且感觉没有什么进步和积累。本质上就是上面5个能力一个也不强,每一步都要卡一下。根据刻意练习理论,一项技能要掌握,就是不停的用,中间的间隔不能太久。就像背书一样,要经常读,要不然就会忘记。
根据这个理论,我们也对上面5项能力进行拆分,然后练习。但不是绝对的拆开,毕竟每做一题都要经历这些过程,只是刻意的去侧重一个方面。
练习方法和步骤:
上面的1,2是偏执行的,自己的思考其实比较少,第三步开始就要慢慢自己思考增多了。
1,2做好了后,基本上leetcode70%的题目都可以解掉。后面3个阶段其实是后期持续要做的。所以1,2阶段的目的是打好基础掌握工具,只要觉得1,2不是自己的瓶颈了,就可以减少练习量,注重后面3步的练习。
下面主要讲练习的材料及服用方法
http://acm.hdu.edu.cn/listproblem.php?vol=11这里面都是一些裸题意思都很明白了,直接从第3步能力开始,自己先思考一下,不会就看题解,然后自己理解,再写代码。可以选择4,5十题集中练习,其他的也可以当作练习题做。
以线段树应用为例
我们可以去搜索大神们总结的题目
ACM大牛总结的线段树专辑
然后,就是按照线段树的思路对题目进行分析。一定要自己先思考,可以规定一个时间,比如2天想不出来,就看看提示或答案,然后把后续的实现做完。
参加比赛:
有了前4步的基础,偶尔也要来一些模拟真实面试训练,比赛就比较真实,题目都是没有见过的,随机的,以赛代练。
看水平而定,水平不高做不出来会打击积极性,但一定要有参加,可能是一个月一次,要有在紧张中思考的经历。赛后做不出来的题,就自己思考,锻炼自己的对于知识工具的应用,对题目的分析抽象能力,主观能动性,主动思考和解决问题。实在想不出来就看看别人的思路,然后自己实现一下。然后把不会的算法找些题再巩固一下。
总结一下,就是
学习过程中的心态也很重要,下面讲讲我的心得。
题目是有难易之分的,有些难题确实很难想到,没有必要去死磕,毕竟我们还有其他的东西要学习。 此时,要看别人的题解,然后努力消化成自己的,至少要把新算法学一学(如果有出现的话)。
面试中,并不是没有思路就挂,有些难题想不出来正常,可以跟面试官说自己的想法。面试官有时候会给一些思路和指导,或者跟你讲一下思路让你实现。此时,如果你的代码能力和数据结构知识有一定积累的话,基本上都可以实现出来的。这也是满足面试要求的。至少不会因为算法题直接挂,还有后续与同等级别的求职者pk环节。
在做了一些题后,总会遇到类似的题,可者写类似的代码,比如说DFS算法,在搜索, dp 等实现的时候都有用到,可以总结出自己的一些模板,然后烂熟于心,一到用时不用思考就可以写出来。还有一些是算法比较的,比如说排序来说有好多种,可能都用过了,也都了解了,但是真正问起来区别一下子答不出来。这些平时要总结一下,想想。用起来的时候就会很清晰,用哪个时可以很快的分析出区别。
面试时一般都是纸上思考和写代码,我们平时线下也要找几题自己模拟一下思考,然后讲述思路和写代码。一般一星期弄一次,要从平时积累,不能临时报佛脚。
面试的目不是为了考倒求职者,是为了考查能力。我们可以针对这些能力针对性的训练并拿到合格的分数,不要因为算法而被挂。
基础特别重要,一定要重点关照一下。
做十道水题不如做一道难题,可以学习到很多新思路和方法。
对于难题不要怕,要以学一个赚一个的心态去想。
要经常总结,形成自己的套路。
要模拟线下笔试,熟悉线下环境。
以上都是一些方法,不花时间再好的方法也没用,一定要抽一些时间出来。最差的坚持也好过放弃,坚持住一定可以的。
最后,水平有限,有误之处还请大家指正。一篇文章不可能讲得很细。大家如果有遇到困惑或难题,可以留言一起讨论。
祝大家多多AC
本人码农,希望通过自己的分享,让大家更容易学懂计算机知识。