双亮双创活动:何海涛谈面试主要考察什么

来源:百度文库 编辑:偶看新闻 时间:2024/05/06 12:04:49

剑指Offer:名企面试官精讲典型编程题 目录

http://baike.baidu.com/view/6809632.htm

第1章 面试的流程
1.1 面试官谈面试
1.2 面试的三种形式
1.2.1 电话面试
1.2.2 共享桌面远程面试
1.2.3 现场面试
1.3 面试的三个环节
1.3.1 行为面试环节
应聘者的项目经验
应聘者掌握的技能
回答“为什么跳槽”
1.3.2 技术面试环节
扎实的基础知识
高质量的代码
清晰的思路
优化效率的能力
优秀的综合能力
1.3.3 应聘者提问环节
1.4 本章小结

第2章 面试需要的基础知识
2.1 面试官谈基础知识
2.2 编程语言
2.2.1 C++ 面试题1:赋值运算符函数
经典的解法,适用于初级程序员
考虑异常安全性的解法,高级程序员必备
2.2.2 C#
面试题2:实现Singleton模式
不好的解法一:只适用于单线程
不好的解法二:可用于多线程但效率不高
可行的解法:同步锁前后两次判断
推荐的解法一:利用静态构造函数
推荐的解法二:按需创建实例
解法比较
2.3 数据结构
2.3.1 数组
面试题3:二维数组中的查找
2.3.2 字符串
面试题4:替换空格 O(n2)的解法,不足以拿到Offer
(n)的解法,搞定Offer就靠它
2.3.3 链表
面试题5:从尾到头打印链表
2.3.4 树
面试题6:重建二叉树
2.3.5 栈和队列
面试题7:用两个栈实现队列
2.4 算法和数据操作
2.4.1 查找和排序
面试题8:旋转数组的最小数字
2.4.2 递归和循环
面试题9:斐波那契数列
效率很低的解法,面试官不会喜欢
面试官期待的实用解法O(logn)但不够实用的解法
解法比较
2.4.3 位运算
面试题10:二进制中1的个数
可能引起死循环的解法
常规解法
能给面试官带来惊喜的解法
2.5 本章小结

第3章 高质量的代码
3.1 面试官谈代码质量
3.2 代码的规范性
3.3 代码的完整性
从3方面确保代码的完整性
3种错误处理的方法
面试题11:数值的整数次方
自以为题目简单的解法
全面但不够高效的解法,离Offer已经很近了
全面又高效的解法,确保能拿到Offer
面试题12:打印1到最大的n位数
跳进面试官陷阱
在字符串上模拟数字加法
把问题转换成数字排列
面试题13:在O(1)时间删除链表结点
面试题14:调整数组顺序使奇数位于偶数前面
只完成基本功能的解法,仅适用于初级程序员
考虑可扩展性的解法,能秒杀Offer
3.4 代码的鲁棒性
面试题15:链表中倒数第k个结点
面试题16:反转链表
面试题17:合并两个排序的链表
面试题18:树的子结构
3.5 本章小结

第4章 解决面试题的思路
面试题19:二叉树的镜像
面试题20:顺时针打印矩阵
面试题21:包含min函数的栈
面试题22:栈的压入、弹出序列
面试题23:从上往下打印二叉树
面试题24:二叉搜索树的后序遍历序列
面试题25:二叉树中和为某一值的路径
面试题26:复杂链表的复制
面试题27:二叉搜索树与双向链表
面试题28:字符串的排列

第5章 优化时间空间效率
面试题29:数组中出现次数超过一半的数字
基于Partition函数的O(n)算法
利用数组特点的O(n)算法
解法比较
面试题30:最小的k个数O(n)的算法,只当可以修改输入数组时可用
O(nlogk)的算法,适合处理海量数据
解法比较
面试题31:连续子数组的最大和
举例分析数组的规律
应用动态规划法
面试题32:从1到n整数中1出现的次数
不考虑效率的解法,想拿Offer有点难
明显提高效率的解法,让面试官耳目一新
面试题33:把数组排成最小的数
面试题34:丑数
逐个判断整数是不是丑数的解法
创建数组保存已经找到的丑数的解法
面试题35:第一个只出现一次的字符
面试题36:数组中的逆序对
面试题37:两个链表的第一个公共结点

第6章 面试中的各项能力
6.1 面试官谈能力
6.2 沟通能力和学习能力
沟通能力
学习能力
善于学习、沟通的人也善于提问
6.3 知识迁移能力
面试题38:数字在排序数组中出现的次数
面试题39:二叉树的深度
重复遍历结点的解法,不足以打动面试官
只遍历结点一次的解法,正是面试官喜欢的
面试题40:数组中只出现一次的数字
面试题41:和为s的两个数字VS和为s的连续正数序列
面试题42:翻转单词顺序 VS左旋转字符串
6.4 抽象建模能力
面试题43:n个骰子的点数
基于递归求骰子点数,时间效率不够高
基于循环求骰子点数,时间性能好
面试题44:扑克牌的顺子
面试题45:圆圈中最后剩下的数字
经典的解法,用循环链表模拟圆圈
创新的解法,拿到Offer不在话下
6.5 发散思维能力
面试题46:求1+2+…+n
利用构造函数求解
利用虚函数求解
利用函数指针求解
利用模板类型求解
面试题47:不用加减乘除做加法
面试题48:不能被继承的类
常规的解法:把构造函数设为私有函数
新奇的解法:利用虚拟继承
6.6 本章小结

第7章 两个面试案例
7.1 案例一:(面试题49)把字符串转换成整数
7.2 案例二:(面试题50)树中两个结点的最低公共祖先  

编程技术面试的五大要点

http://www.programmer.com.cn/8435/
扎实的基础知识、高质量的代码、清晰的思路、优化代码的能力、优秀的综合能力是编程技术面试的五大要点

扎实的基础知识

扎实的基本功是成为优秀程序员的前提条件,因此面试官首要关注应聘者的素质即是否具备扎实的基础。通常基本功在编程面试环节体现在两个方面:一是编程语言,二是数据结构和算法。

每个程序员至少要熟练掌握1~2门编程语言。面试官从应聘者在面试过程中写的代码以及跟进的提问中,能看出他编程语言掌握的熟练程度。以大部分公司面试要求的C++为例,如果函数需要传入一个指针,面试官可能会问是否需要为该指针加上const,把const加在指针不同的位置有什么区别;如果写的函数需要传入的参数是一个复杂类型的实例,面试官可能会问传入值参数或者引用参数有什么区别,什么时候需要为传入的引用参数加上const。

数据结构通常是编程面试过程中考查的重点。在参加面试之前,应聘者需要熟练掌握链表、树、栈、队列以及哈希表等数据结构以及它们的操作。如果我们留心各大公司的面试题,就会发现链表和二叉树相关的问题是很多面试官喜欢问的问题。这方面的问题看似简单,但真正掌握也很不容易,特别适合在短短几十分钟的面试时间内检验应聘者的基本功。如果应聘者事先对链表的插入和删除结点了如指掌,对二叉树的各种遍历方法的循环和递归写法都烂熟于胸,那么真正到了面试时也就游刃有余了。

大部分公司对算法的要求都只是考查查找和排序。应聘者可以在了解各种查找和排序算法的基础上,重点掌握二分查找、归并排序和快速排序,因为很多面试题都只是这些算法的变体而已。比如把排序好的数组的前面若干个数字移到数组的后面,然后问怎样在这个数组之中找到最小的数字。这道题其本质就是考查二分查找。少数对算法很重视的公司比如谷歌或者百度,还会要求应聘者熟练掌握动态规划和贪婪算法。如果对这种类型的公司感兴趣,那么应聘者在参加面试之前就应该加强对相关算法题目的练习。

高质量的代码

只有注重质量的程序员,才能写出鲁棒稳定的大型软件。在面试过程中,面试官总会格外关注边界条件、特殊输入等看似细枝末节但实质至关重要的地方,以此来分析应聘者是否注重代码质量。很多时候,面试官发现应聘者写出来的代码只能完成最基本的功能,一旦输入特殊的边界条件参数就会错误百出甚至程序崩溃。

举个很多应聘者都被问过的一个问题:写一个函数,把字符串转化成整数。这道题看似很简单,绝大部分计算机专业的毕业生都能用十行以内的代码实现最基本的功能。可是在实际面试过程中,十个应聘者中只有一个人能通过这道题的面试,因为绝大部分应聘者不能全面考虑到各种特殊输入,比如输入的字符串含中有非数字的符号、在字符串的开头有正负号、字符串中有正负号但其位置不是在字符串的开头。

除此之外,面试官还希望应聘者能考虑的边界条件包括2147483647(0×7FFFFFFF,int能表示的最大正整数)和-2147483648(0×80000000,int能表示的最小负整数)。

除了边界条件和特殊输入考虑不足之外,面试官还有一个不能容忍的错误就是程序崩溃。面试时很多应聘者都会忘记对空指针做特殊处理而导致程序崩溃。如果面试时遇到链表、二叉树相关的题目,应聘者一定要特别小心。因为这两种题目对应的代码里通常会有大量的指针操作,如果考虑不周到,就有可能对空指针进行操作而使程序崩溃。

比如这样一道题:输入一个链表的头指针和一个无符号整数k,输出该链表的倒数第k个结点。这个题目很多人都能想到用两个指针来解决:第一个指针先在链表上移动k-1步,同时让第一个指针和第二个指针在链表上移动。当第一个指针移动到尾指针时,第二个指针指向的就是倒数第k个结点。然而不是每个应聘者都能根据正确思路写出完整的代码。不少应聘者会忽略两种可能:一是输入的链表头指针有可能是空指针;二是链表上结点的数目有可能少于k个。忽略这两点的代码都存在崩溃的可能,从而很难获得面试官的青睐。

要想写出鲁棒的高质量代码,需要在动手写代码之前想好测试用例。在写代码之前,先要想好各种边界条件和特殊输入作为测试用例。当代码写好之后,自己在心里用之前想好的测试用例来检验自己写出的代码,这样就能在面试官之前发现并解决问题。以求链表的倒数第k个结点为例,如果事先想到了输入头指针为空指针和链表上的结点总数少于k这两个测试用例,并且在写好代码之后在心里模拟代码的运行过程,确保能够通过这两个测试用例的测试,那么这轮面试必然是能够通过的。

清晰的思路

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

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

首先是举几个简单的具体例子让自己理解问题。当一眼看不出问题中隐藏的规律时,可以试着用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个丑数。很多人都没有听说过丑数这个概念。这时面试官就会观察应聘者面对丑数这个新概念,能不能经过提问、思考、再提问的过程,最终找出丑数的规律从而找到解决方案。

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

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

小结

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

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