程序员面试中,不少算法设计问题,都是历年来各家企业的“炒现饭”,无论求职者之前对算法知识学习得是否扎实,理解得是否深刻,只要面试前买本《程序员面试笔试宝典》(备注:编者早前编写的一本书,机械工业出版社出版),学习上一段时间,牢记于心,应付此类题目彻底没有问题,但遗憾的是,不少世界级知名企业也深知这一点,若是纯粹是出一些毫无技术含量的题目的话,对于考前“突击手”而言,可能会占尽便宜,但对于那些技术好的人而言是很是不公平的。因此,为了把优秀的求职者与通常的求职者可以更好地区分开来,他们愈来愈倾向于出一些有技术含量的“新”题,这些题目以及答案,再也不是之前的陈谷子烂芝麻了,而是通过精心设计的好题。程序员
在程序员面试中,算法的地位就如同是GRE或托福考试在出国中的地位同样,必须但不是最重要的,它只是众多考核方面中的一个而已,不必定就能决定求职者的生死。虽然如此,但并不是说明就不用去准备算法知识了,由于算法知识回答得好,必然会成为面试的加分项,对于求职成功,百利而无一害。那么如何应对此类题目呢?很显然,编者不可能将此类题目都在《程序员面试笔试宝典》中一一解答,一来因为内容众多,篇幅有限,二来也不必,今年考过了,之后通常就不会再考了,否则仍是没有区分度。编者觉得,靠死记硬背确定是行不通的,解答此类算法设计问题,须要求职者具备扎实的基本功以及良好的运用能力,编者没法左右求职者的我的基本功以及运用能力,由于这些能力须要求职者“十年磨一剑”地苦学,但编者能够提供一些比较好的答题方法和解题思路,以供求职者在面试时应对此类算法设计问题。“授之以鱼不如授之以渔”,岂不是更好?面试
(1)概括法算法
此方法经过写出问题的一些特定的例子,分析总结其中通常的规律。具体而言就是经过列举少许的特殊状况,通过分析,最后找出通常的关系。例如,某人有一对兔子饲养在围墙中,若是它们每月生一对兔子,且新生的兔子在第二个月后也是每月生一对兔子,问一年后围墙中共有多少对兔子。设计模式
使用概括法解答此题,首先想到的就是第一个月有多少对兔子,第一个月的时候,最初的一对兔子生下一对兔子,此时围墙内共有两对兔子。第二个月还是最初的一对兔子生下一对兔子,共有3对兔子。到第三个月除最初的兔子新生一对兔子外,第一个月生的兔子也开始生兔子,所以共有5对兔子。经过举例,能够看出,从第二个月开始,每个月兔子总数都是前两个月兔子总数之和,Un+1=Un+Un-1,一年后,围墙中的兔子总数为377对。数组
此种方法比较抽象,也不可能对全部的状况进行列举,因此,得出的结论只是一种猜想,还须要进行证实。数据结构
(2)类似法学习
正如编者“年年岁岁花类似,岁岁年年仍单身”同样,此方法考虑解决问题的算法是类似的。若是面试官提出的问题与求职者之前用某个算法解决过的问题类似,此时此刻就能够举一反三,尝试改进原有算法来解决这个新问题。而一般状况下,此种方法都会比较奏效。网站
例如,实现字符串的逆序打印,也许求职者历来就没遇到过此问题,但将字符串逆序确定在求职准备的过程当中是见过的。将字符串逆序的算法稍加处理,便可实现字符串的逆序打印。spa
(3)简化法设计
此方法首先将问题简单化,例如改变一下数据类型、空间大小等,而后尝试着将简化后的问题解决,一旦有了一个算法或是思路能够解决这个被“阉割过”的问题,再将问题还原,尝试着用此类方法解决原有问题。
例如,在海量日志数据中提取出某日访问xxx网站次数最多的那个IP。很显然,因为数据量巨大,直接进行排序不可行,但若是数据规模不大时,采用直接排序不失为一种好的解决方法。那么如何将问题规模缩小呢?因而想到了Hash法,Hash每每能够缩小问题规模,而后在“阉割过”的数据里面使用常规排序算法便可找出此问题的答案。
(4)递归法
为了下降问题的复杂度,不少时候都会将问题逐层分解,最后归结为一些最简单的问题,这就是递归。此种方法,首先要可以解决最基本的状况,而后以此为基础,解决接下来的问题。
例如,在寻求全排列的时候,可能会感受无从下手,但仔细推敲,会发现后一种排列组合每每是在前一种排列组合的基础上进行的从新排列,只要知道了前一种排列组合的各种组合状况,只须要把最后一个元素插入到前面各类组合的排列里面,就实现了目标:即先截去字符串s[1…n]中的最后一个字母,生成全部s[1…n-1]的全排列,而后再将最后一个字母插入到每个可插入的位置。
(5)分治法
任何一个能够用计算机求解的问题所需的计算时间都与其规模有关。问题的规模越小,越容易直接求解,解题所需的计算时间也越少。而分治法正是充分考虑到这一点内容,将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。分治法通常包含如下三个步骤:1)将问题的实例划分为几个较小的实例,最好具备相等的规模;2)对这些较小的实例求解,而最多见的方法通常是递归;3)若是有必要的话,合并这些较小问题的解,以获得原始问题的解。
分治法是程序员面试常考的算法之一,通常适用于二分查找、大整数相乘、求最大子数组和、找出伪币、金块问题、矩阵乘法、残缺棋盘、归并排序、快速排序、距离最近的点对、导线与开关等。
(6)Hash法
不少面试笔试题目,都要求求职者给出的算法尽量高效。什么样的算法是高效的?通常而言,时间复杂度越低的算法越高效。而要想达到时间复杂度的高效,不少时候就必须在空间上有所牺牲,用空间来换时间。而用空间换时间最有效的方式就是Hash法、大数组、位图法。固然,此类方法并不是包治百病,有时,面试官也会对空间大小进行限制,那么,此时,求职者只能再去思考其余的方法了。
其实,凡是涉及到大规模数据处理的算法设计中,Hash法就是最好的方法之一。
(7)轮询法
每道面试笔试题,在设计时,每每会有一个载体,这个载体即是数据结构,例如数组、链表、二叉树、图等,当载体肯定后,可用的算法天然而然地就会暴露出来。可问题是不少时候并不肯定这个载体是什么。当没法肯定这个载体时,通常也就很难想到合适的方法了。
编者建议,此时,求职者能够采用最原始的思考问题的方法——轮询,在脑海中轮询各类可能的数据结构与算法,常考的数据结构与算法一共就那么一些,即便不彻底同样,也是由此衍生出来的或是类似的,总有一款适合此题的。
表7.1 最常考的数据结构与算法知识点
数据结构 |
算法 |
概念 |
链表 |
广度(深度)优先搜索 |
位操做 |
数组 |
递归 |
设计模式 |
二叉树 |
二分查找 |
内存管理(堆、栈等) |
树 |
排序(归并排序、快速排序等) |
|
堆(大顶堆、小顶堆) |
树的插入/删除/查找/遍历等 |
|
栈 |
图论 |
|
队列 |
Hash法 |
|
向量 |
分治法 |
|
哈希表 |
动态规划 |
|
此种方法看似笨拙,其实实用,只要求职者对常见的数据结构与算法烂熟于心,一点都没有问题。
为了更好的理解这些方法,求职者能够在平时的准备过程当中,应用此类方法去答题,作得多了,天然对各类方法也就熟能生巧了,面试的时候,再遇到此类问题,也就可以收放自如了。固然,千万不要相信有着张无忌般的运气,可以在一晚上之间练成乾坤大挪移这一绝世神功,称霸武林,算法设计功力的练就靠得是平时一点一滴的付出和思惟的磨练。方法与技巧也许只是给面试打了一针“鸡血”、喂一口大补丸,让本身变得从容自信,真正的内力仍是一个长期的积累过程,不是速食产品可以比得了的。
明年就要就业了,这里看到好的东西共享一下,但愿对你们有所帮助,一样也是给本身加油!