本文来自 酷壳 – CoolShell.cn 陈皓 撰写的文章:html
算法面试多是微软搞出来的面试方法,如今不少公司都在效仿,并且咱们的程序员也乐于解算法题,我我的觉得,这是应试教育的毒瘤!我在《再谈“我是怎么招程序员”》中比较保守地说过,“问难的算法题并无错,错的不少面试官只是在肤浅甚至错误地理解着面试算法题的目的。”,今天,我想增强一下这个观点——我反对纯算法题面试!(注意,我说的是纯算法题)程序员
我再次引用我之前的一个观点——面试
能解算法题并不意味着这我的就有能力就能在工做中解决问题,你能够想一想,小学奥数题可能比这些题更难,但并不意味着那些奥数能手就能解决实际问题。算法
好了,让咱们来看一个示例(这个示例是昨天在微博上的一个讨论),这个题是——“找出无序数组中第2大的数”,几乎全部的人都用了O(n)的算法,我相信对于咱们这些应试教育出来的人来讲,不用排序用O(n)算法是很正常的事,连我都不禁自主地认为O(n)算法是这个题的标准答案。咱们太习惯于标准答案了,这是我国教育最悲哀的地方。(广义的洗脑就是让你的意识依赖于某个标准答案,而后经过给你标准答案让你不会思考而控制你)shell
试想,若是咱们在实际工做中获得这样一个题 咱们会怎么作?我必定会分析这个需求,由于我惧怕需求将来会改变,今天你叫我找一个第2大的数,明天你找我找一个第4大的数,后天叫我找一个第100大的 数,我不搞死了。需求变化是很正常的事。分析完这个需求后,我会很天然地去写找第K大数的算法——难度一会儿就增大了。编程
不少人会觉得找第K大的需求是一种“过早扩展”的思路,不是这样的,我相信咱们在实际编码中写过太多这样的程序了,你必定不会设计出这样的函数接口 —— Find2ndMaxNum(int* array, int len),就好像你不会设计出 DestroyBaghdad(); 这样的接口,而是设计一个DestoryCity( City& ); 的接口,而把Baghdad当成参数传进去!因此,你应该是声明一个叫FindKthMaxNum(int* array, int len, int kth),把2当成参数传进去。这是最基本的编程方法,用数学的话来讲,叫代数!最简单的需求分析方法就是把需求翻译成函数名,而后看看是这个接口不是很二?!数组
(注:不要纠结于FindMaxNum()或FindMinNum(),由于这两个函数名的业务意义很清楚了,不像Find2ndMaxNum()那么二)数据结构
性能之类的东西历来都是非功能性需求,对于算法题,咱们太喜欢研究算法题的空间和时间复杂度了。咱们但愿作到空间和时间双丰收,这是算法学术界的风格。因此,习惯于标准答案的咱们已经失去思考的能力,只会机械地思考算法以内的性能,而忽略了算法以外的性能。函数
若是题目是——“从无序数组中找到第K个最大的数”,那么,咱们必定会去思考用O(n)的线性算法找出第K个数。事实上,也有线性算法——STL中 能够用nth_element求得相似的第n大的数,其利用快速排序的思想,从数组S中随机找出一个元素X,把数组分为两部分Sa和Sb。Sa中的元素大 于等于X,Sb中元素小于X。这时有两种状况:1)Sa中元素的个数小于k,则Sb中的第k-|Sa|个元素即为第k大数;2) Sa中元素的个数大于等于k,则返回Sa中的第k大数。时间复杂度近似为O(n)。性能
搞学术的nuts们到了这一步必定会欢呼胜利!可是他们哪里能想获得性能的需求分析也是来源自业务的!
咱们一说性能,基本上是我的都会问,请求量有多大?若是咱们的FindKthMaxNum()的请求量是m次,那么你的这个每次都要O(n)复杂度的算法获得的效果就是O(n*m),这一点,是书呆子式的学院派人永远想不到的。由于应试教育让咱们不会从实际思考了。
根据上面的需求分析,有软件工程经验的人的解法一般会这样:
1)把数组排序,从大到小。
2)因而你要第k大的数,就直接访问 array[k]。
排序只须要一次,O(n*log(n)),而后,接下来的m次对FindKthMaxNum()的调用全是O(1)的,总体复杂度反而成了线性的。
其实,上述的还不是工程式的最好的解法,由于,在业务中,那数组中的数据可能会是会变化的,因此,若是是用数组排序的话,有数据的改动会让我从新排序,这个太耗性能了,若是实际状况中会有不少的插入或删除操做,那么能够考虑使用B+树。
工程式的解法有如下特色:
1)很方便扩展,由于数据排好序了,你还能够方便地支持各类需求,如从第k1大到k2大的数据(那些学院派写出来的代码在拿到这个需求时又开始挠头苦想了)
2)规整的数据会简化总体的算法复杂度,从而总体性能会更好。(顺序的处理很容易进行各类处理)
3)代码变得清晰,易懂,易维护!(学院派的和STL同样的近似O(n)复杂度的算法没人敢动)
你必定会和我争论,
看过这上面的分析,我相信你明白我为何反对纯算法面试题了。缘由就是纯算法的面试题根本不能反应一个程序的综合素质!
那么,在面试中,咱们应该要考量程序员的那些综合素质呢?我觉得有下面这些东西:
另外,咱们知道,对于软件开发来讲,在工程上,难是的下面是这些挑战:
因此,对于编程能力上,咱们应该主要考量程序员的以下能力:
因此,这段时间,我愈来愈倾向于问应聘者一些有业务意义的题,并且应增长或更改需求来看程序员的重构代码的能力,写完程序后,让应聘者设计测试案例。
好比:解析加减乘除表达式,字符串转数字,洗牌程序,口令生成器,经过ip地址找地点,英汉词典双向检索……
总之,我反对纯算法面试题!