摘自:《程序员的呐喊》
算法复杂度:大O是一定要懂得。如果连基本的大O复杂度分析都磕磕绊绊,那基本上是肯定过不了面试的。它最多是计算机理论里开头的一章内容,所以一定要去读。你能读懂的。
排序:知道排序是怎么回事,不要写冒泡。至少也要了解一个复杂度为n*log(n)的排序算法的细节。能记住两个更好(比如快速排序和归并排序)。归并排序在那些快速排序不好用的的情况下通常都很有用。所以应该了解一下。
无论如何,也不要在面试的时候去排序一个链表。
哈希表:哈希表可以说是人类已知的最重要的数据结构。一定要弄明白它的原理是什么。它也就是数据结构书里的一个章节。去读吧。你要能够做到在一场面试里,用自己熟悉的语言,只用数组来实现它。
树:必须弄懂。这是基础,我真的不想说,但是有些人连最基本的怎么构造一课树,怎么遍历,怎么操作的算法都没搞明白就来面试,太丢人啦。你至少也应该熟悉二叉树、n叉树、trie树。树应该是长期热身里最好的练习题资源了。
至少熟悉一种平衡二叉树,可以是红黑树、伸展树、AVL树。而且必须掌握实现细节。
树的遍历算法也要知道,BFS和DFS。还要了解前序、中序、后序遍历的区别。
可能是你用的很少,但是因为你在回避它。只要你弄懂树,就不用再害怕啦。好好学吧。
图:图真的是非常重要。远超你的现象。就算你已经觉得它很重要,很可能它的重要性还是超过了你的认知。
在内存里表示图的方法基本上有三种(对象和指针、矩阵、邻接表),每种表示都要熟悉,并且知道它们的优缺点。
你应该了解基本的图遍历算法,广度优先搜索和深度优先搜索。知道它们的计算复杂度、优缺点,已经具体的实现代码。
然后还应该根据情况了解一些更高级的算法,如Dijkstra算法和A*算法。无论是在游戏编程中还是在分布式计算中,这些都是非常了不起的算法,所以应该了解一下。
每次遇到问题,首先应当考虑的就是图算法。它们是任何关系最基本、最灵活的表示方法,任何有点意思的设计问题可以说有一半的机会会涉及图算法。只有在你百分之百确定没办法用图算法来解的时候,才能考虑其他方案。这条建议一定要牢记在心!
其他数据结构
只要脑袋装的下,就尽可能多地掌握一点各种数据结构和算法。特别是那些著名的NP问题,如旅行商问题和背包问题。在面试官问到这类问题的时候,你要能认出来。
你应该知道NP完全问题是什么意思。
一定要好好读数据结构书,能记多少是多少,相信我,你不会失望的。
数学:有些面试官会问一些基本的离散数学。在Google似乎这种现象比其他地方都要流行。虽然我自己也不是很擅长数学,不过我觉得这算是好事吧。我们身边有各种计数问题、概率问题,以及其他的基本的离散数学,而我们周围的数学盲却在用拙劣的方法绕过它们,完全不知道自己在干嘛。
要是面试官真的问数学问题也不要生气。尽力就好。要是能在面试之前复习一下基本的组合学和概率学,你的表现会出色很多。至少也要熟悉n选k这类问题——多多益善。
可时间不够用啊,我懂得。但是是否听从这些建议的区别就是“不好说啊”和“就是她啦”。其实离散数学也不是那么难——很多高中里学过又忘了的数学都派不上用场。只要懂小学数学就可以了,所以花个两天时间好好学一下就能捡起来。
操作系统:你只要知道进程、线程、并发这些概念就够了。很多面试官都会问到这些基础内容,所以你应该了解它们。掌握锁的概念,互斥锁、信号量,管程机制的工作方式。知道什么是死锁,什么是活锁,怎么避免它们。知道进程需要哪些资源,线程需要哪些资源,上下文切换时怎么进行。知道一点调度是怎么回事。现在多核正在变得越来越流行,要是你连基本的现代(或者说有时工作有时失灵)并发结构不理解的话,那就真的是史前动物了。
这方面我读过的最实用的的书就是道格*李的《Java并发进程》。每一页都是真知灼见。讲并发的书其实很多。不过一般我不会去读学术著作,而是喜欢关注更实用的方面,毕竟这些才是在面试中比较容易碰到的。
编程:至少要熟练掌握一种编程语言,最好是C++或者Java。C#也行,反正它和Java很像。一轮面试下来,至少有几场是要写代码。所以一定要对那门语言的细节有相当程度的了解。
其他
尽管我列出各种规则,但遇到面试官A的可能性依然存在,这时再怎么根据我的建议学习都是没用的(热身的部分除外)。尽力而为吧。最坏的情况也不过是再等几个月。对吧?看起来时间很长,其实一眨眼就过去了,我保证。
我上面提到的这些东西其实都是必备知道:要是这些都不懂,基本过不了面试。离散数学的要求或许没那么严格,但是一点也不懂得话好像也说不过去。剩下的内容都要融会贯通,这样就算是达到面试的及格线了。根据不同面试官的风格,面试的难度可能会很高,也可能简单的多。
这真的是要看你的运气如何。你觉得自己是不是有运气的人?来试试看吧。