如何通过训练使自己能在面试中能顺利解答算法问题?

算法面试中一般要求面试者能够在规定的时间(一般40分钟左右)解答两道甚至是三道算法题目。对面试者的挑战包括寻找答题所需要的数据结构和算法的能力,以及快速精准地写出代码的能力。个人认为算法面试的初衷是要测试面试者在计算机编程方面的基础,因此在某种程度上讲,基础越好,能力越强的面试者能够有出色发挥的可能性越大。但是,由于算法问题实际上很大程度脱离计算机行业日常的工作内容,因此在没有训练的情况下,对优秀的码农依然会是一个较大的挑战。另一个方面,由于算法面试题目的范围有限并且相对较窄,通过有目的性的训练可以对面试的表现有极大的提升。

题海战术

那么应该如何有目的性地进行算法面试的训练呢?如果你的时间非常有限,题海战术可能是最高效最适合的方法。题海战术指的是做大量的面试原题,通过记忆题目的答案,以期在面试中能够很幸运地遇到做过的题目,或者与做过题目相似的题目,从而能够将面试的答案“默写”出来。

在撞对题目的情况下,面试者往往能够有相对清晰的思路,并且能快速精准地写出程序。因此题海战术实际上使面试者从需要具备过硬的编程能力,变成只需要一个靠谱的题库,足够的练习以及一点运气(当然,你还是要有一定编程基础的)。

现在市面上有不少提供题库的公司,本人练习时使用的是leetcode,质量还不错,不过我估计不同题库之间也是大同小异,选择自己喜欢的就好。题海战术强调的是高质量的练习,个人认为最关键的是制订好计划以及严格专注的执行。为了最大限度的提升效率,本人的计划是先确定好要做的题目(根据要面试的公司以及leetcode提供的相关公司的分类),然后通过参考答案快速地将题目理解并做出来,接着在不参考答案的情况下再做一遍题目,记下那些依然无法快速做完的题目,然后在面试前将那些记下来的题目再做一遍。本人前后花了大概三个月的时间,完成了600多道题(大概是最初计划的80%)。

这里是本人做过问题的代码以及部分问题的解析。

基础知识

题海战术虽然直观高效,但是有两个比较致命的问题。一是当你在面试中遇到完全没有做过的问题,你会相当被动,因为你并没有足够的经验来探索一道未知题目的解法。二是解答算法题目本身也是提高编程能力的一种练习,题海战术让你失去了更加深入思考和训练的机会。

那么应该如何提高解题和编程能力,从而即使是完全没有遇到过问题也很大概率可以应对自如呢?

个人认为,获得解答算法问题的能力跟获得其它能力–比如说弹钢琴–的方法是相似的。学钢琴的时候你会先练习弹奏一些基本的入门曲目来熟悉钢琴本身,然后通过学习和练习基本的指法来打基础,最后循序渐进地练习各种难度的曲目来提高能力。一旦你有良好的基础和足够的练习,即使是面对一首你从来没有碰到过的钢琴曲,你也可以相对快速地掌握。(本人只是附庸风雅的学了几个月钢琴,所以如果以上理解有错请多多包涵。)相应的,学习解答算法问题可以先接触一定数量的简单题目来对解题本身有一个初步的感受,接着学习基本的解题工具和技巧,最后通过大量的练习来达到融会贯通。

那么哪些是解题需要的基本工具呢?个人觉得可以概括为我们经常说到的数据结构和算法。数据结构是指数据存储和组织的方式。计算机经过多年的发展,众多研究者已经为我们提供了各种具体实用的结构。每一种结构都有其相对的设计意图,针对某些操作提供让人满意的效率。通过使用正确有效的数据结构,可以让我们满足解答题目所需要的效率要求。另一方面,算法指的是解决某种问题的有效步骤。研究者通过对经典问题的研究和总结,为我们提供了解决某些问题的最佳方法。算法问题很多时候要么可以被分解成若干个经典问题,要么可以转换成某个经典问题。因此掌握经典的算法犹如掌握解决数学题的基本公式。

基于以上的认识,也寄希望于自己能够更好的掌握,我根据自己的理解收集和整理各种数据结构和算法,并总结如下

数据结构

算法

寻找解题思路

由上而下和由下而上

大量的练习

据说即使是最出色的算法题解题者,也需要通过大量的练习来保持最高的水准。因此,要做到对基础知识的融汇贯通,要做到对已知未知的题目都得心应手,我们必须要有有足够的练习。

某种程度讲,我们似乎又回到了题海战术上,只是不同的是,因为有了对知识内在的理解,我们解题不再只留在表面,而是通过完成越来越多的题目,我们更加了解出题者如何通过将基础的数据结构与算法进行组合和修饰,从而变成一道考验面试者的题目。这种对内在关联的了解,以及应对这些关联的经验,正式解决未知问题的关键。

以下是我练习过的题目的整理,以及相关的分类。

希望我们可以一起可以通过不断地学习和练习,让成功完成算法面试不再是一个不可完成的任务。