清晰的思路

  只有思路清晰,应聘者才有可能在面试过程中解决复杂的问题。有时面试官会有意出一些比较复杂的问题,以考查能否在短时间内形成清晰的思路并解决问题。对于确实很复杂的问题,面试官甚至不期待应聘者能在面试不到一个小时的时间里给出完整的答案,他更看重的可能还是应聘者是否有清晰的思路。面试官通常不会喜欢应聘者在没有形成清晰思路之前草率地开始写代码,结果写出来的代码容易逻辑混乱、错误百出。

  应聘者可以用几个简单的方法帮助自己形成清晰的思路。

  首先是举几个简单的具体例子让自己理解问题。当一眼看不出问题中隐藏的规律时,可以试着用1~2个具体的例子模拟操作的过程,这样说不定能通过具体的例子找到抽象的规律。

  其次可以试着用图形表示抽象的数据结构。像分析与链表、二叉树相关的题目时,可以画出它们的结构图来简化题目。

  后可以试着把复杂的问题分解成若干个简单的子问题,再一一解决。很多基于递归的思路,包括分治法和动态规划法,都是把复杂的问题分解成一个或者多个简单的子问题。

  比如把二叉搜索树转化排序的双向链表这个问题很复杂。碰到这个问题,不妨先画出1~2个具体的二叉搜索树及其对应的排序双向链表,直观地感受二叉搜索树和排序的双向链表有哪些联系。如果一下子找不出转换的规律,可以把整个二叉树看出三部分:根结点、左子树和右子树。当递归地把转换左右子树这两个子问题解决之后,再把转换左右子树得到的链表和根结点链接起来,整个问题也解决了。

  优化代码的能力

  的程序员对时间和空间的消耗锱铢必较,他们很有激情不断优化自己的代码。当面试官出的题目有多种解法时,通常他会期待应聘者终能够找到优解。这要求应聘者在面试官提示还有更好的解法时,不能放弃思考,而应该努力寻找在时间消耗或者空间消耗上可以优化的地方。

  要想优化时间或者空间效率,首先要知道如何分析效率。即使是同一个算法,用不同方法实现的效率可能也会大不相同,要能够分析出算法及其代码实现的效率。例如求斐波那契数列,很多人喜欢用递归公式f(n)=f(n-1)+f(n-2)求解。如果分析它的递归调用树,会发现有大量的计算是重复的,时间效率是以n的指数增加。但如果先求f(1)、f(2),再根据f(1)和f(2)求出f(3),接下来根据f(2)、f(3)求出f(4),并以此类推用一个循环求出f(n),这种计算方法的时间效率只有O(n),比前面递归的方法要好很多。

  要想优化代码的效率,还要熟知各种数据结构的优缺点,并能选择合适的数据结构解决问题。我们在数组中根据下标可以用O(1)完成查找。数组的这个特征可以用来实现简单的哈希表解决很多面试题,比如在字符串中找到第一个只出现一次的字符。再比如为了找出n个数字中小的k个数,需要一个数据容器来存储k个数字。在这个数据容器中,我们希望能够快速地找到大值并且能快速地替换其中的数字。经过权衡,我们发现二叉树比如大堆或者红黑树都是实现这个数据容器的理想选择。

  要想优化代码的效率,也要熟练掌握常用的算法。面试中常用的算法是查找和排序。如果从头到尾顺序扫描一个数组,需要O(n)时间才能完成查找操作。但如果数组是排序的,应用二分查找算法能把时间复杂度降低到O(logn)。排序算法除了能够给数组排序之外,还能用来解决其他问题。比如快速排序算法中的Partition函数能够用来在n个数里查找第k大的数字,从而可以用O(n)的时间在数组中找到出现次数超过数组长度一半的数字。如果面试题是一个求大值或者小值的题目,则可以尝试用动态规划法或者贪婪算法,比如用动态规划法求出数组中连续子数组的大和。

  的综合能力

  在面试过程中,应聘者除了展示自己的编程能力和技术功底之外,还需要展示自己的软技能,诸如沟通能力和学习能力。随着软件系统的规模越来越大,软件开发已经告别了单打独斗的年代,程序员与他人的沟通变得越来越重要。在面试过程中,面试官会观察应聘者在介绍项目经验或者算法思路时是否观点明确、逻辑清晰,并以此判断他沟通能力的强弱。另外,面试官也会从应聘者说话的神态和语气来判断他是否有团队合作的意识。通常面试官不会喜欢高傲或者轻视合作者的人。

  IT行业知识更新很快,因此程序员只有具备很好的学习能力才能跟上知识更替的步伐。通常面试官有两种办法考查应聘者的学习能力。第一种方法是询问应聘者近在看什么书、从中学到了哪些新技术。面试官可以用这个问题了解应聘者的学习愿望和学习能力。第二种方法是抛出一个新概念,接下来他会观察应聘者能不能在较短时间内理解这个新概念并解决相关的问题。比如面试官要求应聘者计算第1500个丑数。很多人都没有听说过丑数这个概念。这时面试官会观察应聘者面对丑数这个新概念,能不能经过提问、思考、再提问的过程,终找出丑数的规律从而找到解决方案。
$news_paage$

  知识迁移能力是一种特殊的学习能力。如果我们能够把已经掌握的知识迁移到其他领域,那么学习新技术或者解决新问题会变得容易。面试官经常会先问一个简单的问题,再问一个很复杂但和前面的简单问题相关的问题。这时面试官期待应聘者能够从简单问题中得到启示,从而找到解决复杂问题的窍门。比如面试官先要求应聘者写一个函数求斐波那契数列,再问一个青蛙跳台阶的问题:一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶,请问这只青蛙跳上n级的台阶总共有多少种跳法?应聘者如果具有较强的知识迁移能力,能分析出青蛙跳台阶问题实质上只是斐波那契数列的一个应用。

  还有不少面试官喜欢考查应聘者的抽象建模能力和发散思维能力。面试官从日常生活中提炼出问题,比如如何判断5张扑克牌是不是顺子,考查应聘者能不能把问题抽象出来用合理的数据结构表示,并找到其中的规律解决这个问题。面试官也可以限制应聘者不得使用常规方法,这要求应聘者具备创新精神,能够打开思路从多角度去分析、解决问题。比如面试官要求应聘者不用加减乘除四则运算实现两个整数的加法。此时面试官期待应聘者能够打开思路,用位运算实现整数的加法。

  小结

  我们可以用下图来总结出应聘者需要具备的素质。

  从上图可以看出,应聘者在面试之前需要做足准备,对编程语言、数据结构和算法等基础知识有全面的了解。面试时如果碰到简单的问题应聘者一定要注重细节写出完整、鲁棒的代码。如果碰到复杂的问题应聘者可以通过画图、举具体例子分析和分解复杂问题等方法先理清思路再动手编程。除此之外,应聘者还应该不断优化时间效率和空间效率,力求找到优的解法。在面试过程中,应聘者还应该主动提问弄清楚题目的要求,表现自己的沟通能力。当面试官前后问的两个问题有相关性时,尽量把解决前面问题的思路迁移到后面的问题中去,展示自己良好的学习能力。如果能做到这么几点,那么应聘者顺利通过面试获得心仪的职位将是瓜熟蒂落的事情。