范文无忧网面试笔试面试回答

为什么我反对纯算法面试题

02月24日 编辑 fanwen51.com

[腾讯的一道笔试算法题解答]假设有这样一种字符串,它们的长度不大于 26 ,而且若一个这样的字符串其长度为 m ,则这个字符串必定由 a, b, c ... z 中的前 m 个字母构成,同时我们保证每个字母出现且仅出现一...+阅读

为什么我反对纯算法面试题

我在《再谈“我是怎么招程序员”》中比较保守地说过,“问难的算法题并没有错,错的很多面试官只是在肤浅甚至错误地理解着面试算法题的目的。”,今天,我想加强一下这个观点——我反对纯算法题面试!(注意,我说的是纯算法题)图片源Wikipedia(点击图片查看词条)我再次引用我以前的一个观点——能解算法题并不意味着这个人就有能力就能在工作中解决问题,你可以想想,小学奥数题可能比这些题更难,但并不意味着那些奥数能手就能解决实际问题。好了,让我们来看一个示例(这个示例是昨天在微博上的一个讨论),这个题是——“找出无序数组中第2大的数”,几乎所有的人都用了O(n)的算法,我相信对于我们这些应试教育出来的人来说,不用排序用O(n)算法是很正常的事,连我都不由自主地认为O(n)算法是这个题的标准答案。

我们太习惯于标准答案了,这是我国教育最悲哀的地方。(广义的洗脑就是让你的意识依赖于某个标准答案,然后通过给你标准答案让你不会思考而控制你)功能性需求分析试想,如果我们在实际工作中得到这样一个题 我们会怎么做?我一定会分析这个需求,因为我害怕需求未来会改变,今天你叫我找一个第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)复杂度的算法没人敢动)争论你可能会和我有以下争论,如果程序员做这个算法题用排序的方式,他一定不会像你想那么多。

是的,你说得对。但是我想说,很多时候,我们直觉地思考,恰恰是正确的路。因为“排序”这个思路符合人类大脑处理问题的方式,而使用学院派的方式是反大脑直觉的。反大脑直觉的,通常意味着晦涩难懂,维护成本上升。就是一道面试题,我就是想测试一下你的算法技能,这也扯太多了。没问题,不过,我们要清楚我们是在招什么人?是一个只会写算法的人,还是一个会做软件的人?这个只有你自己最清楚。这个算法题太容...

算法面试

我在《再谈“我是怎么招程序员”》中比较保守地说过,“问难的算法题并没有错,错的很多面试官只是在肤浅甚至错误地理解着面试算法题的目的。”,今天,我想加强一下这个观点——我反对纯算法题面试!(注意,我说的是纯算法题)图片源Wikipedia(点击图片查看词条)我再次引用我以前的一个观点——能解算法题并不意味着这个人就有能力就能在工作中解决问题,你可以想想,小学奥数题可能比这些题更难,但并不意味着那些奥数能手就能解决实际问题。好了,让我们来看一个示例(这个示例是昨天在微博上的一个讨论),这个题是——“找出无序数组中第2大的数”,几乎所有的人都用了O(n)的算法,我相信对于我们这些应试教育出来的人来说,不用排序用O(n)算法是很正常的事,连我都不由自主地认为O(n)算法是这个题的标准答案。

我们太习惯于标准答案了,这是我国教育最悲哀的地方。(广义的洗脑就是让你的意识依赖于某个标准答案,然后通过给你标准答案让你不会思考而控制你)功能性需求分析试想,如果我们在实际工作中得到这样一个题 我们会怎么做?我一定会分析这个需求,因为我害怕需求未来会改变,今天你叫我找一个第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)复杂度的算法没人敢动)争论你可能会和我有以下争论,如果程序员做这个算法题用排序的方式,他一定不会像你想那么多。

是的,你说得对。但是我想说,很多时候,我们直觉地思考,恰恰是正确的路。因为“排序”这个思路符合人类大脑处理问题的方式,而使用学院派的方式是反大脑直觉的。反大脑直觉的,通常意味着晦涩难懂,维护成本上升。就是一道面试题,我就是想测试一下你的算法技能,这也扯太多了。没问题,不过,我们要清楚我们是在招什么人?是一个只会写算法的人,还是一个会做软件的人...

今天参加了华为的面试被一个算法题水了

根据要求修改了,复杂度为O(n),没有引入额外的数组:)

#include

#define N 7

void main(){

int a[N],step,temp;

printf("输入%d个整数:\n",N);

for(int l=0;l

scanf("%d",&a[l]);

printf("输入步长:\n");

scanf("%d",&step);

step=step%N;

int k=0,n=0;

for(int i=step;i

if(step)

k=k%step;

n=i%N;

temp=a[n];

a[n]=a[k];

a[k]=temp;

}

printf("输出移位后的数组:\n");

for(int m=0;m

printf("a[%d]=%d\n",m,a[m]);

}

延伸阅读:

java算法面试题排序都有哪几种方法一、冒泡排序 [java] view plain copy package sort.bubble; import java.util.Random;/*** 依次比较相邻的两个数,将小数放在前面,大数放在后面* 冒泡排序,具有稳定性* 时间复...

谷歌面试题中关于算法的问题的具体解答过程谷歌面试题: 平面上N个点,求一条直线,穿过的点数最多 思路:2点确定一条线,N个点共有n(n-1)/2条线,穿过的点数最多的直线,斜率相同的最多,因此只要找出相同斜率最多的点对集合,并且有...

一道面试算法这是典型的桶排序算法, 假设有9个桶,每个桶里存放N个数字。桶应该是唯一的。 所以推出结论: 1。桶是唯一的(我们因此可以利用Hashtable的唯一性来做到); 2。桶内成员可以不排序,因...

今天参加了华为的面试被一个算法题水了根据要求修改了,复杂度为O(n),没有引入额外的数组:) #include <stdio.h> #define N 7 void main(){ int a[N],step,temp; printf("输入%d个整数:\n",N); for(int l=0;l<N;l++) scanf(...

java算法面试题:排序都有哪几种方法一、冒泡排序 [java] view plain copy package sort.bubble; import java.util.Random;/*** 依次比较相邻的两个数,将小数放在前面,大数放在后面* 冒泡排序,具有稳定性* 时间复...

我后天面试护士谁能告诉我考什么题第一是专业知识第二是专业精神第三是天生的耐心细心的性格有的医院的面试就是考护理操作的意思,专业点的说法就是考实践技能。而有些医院的面试只是目测一下应试者的身高,相貌...

为什么最难不过二叉树的算法出现在面试题中都会被应聘者抱怨以下是某位经历者的答复: 最简单的解释:典型的工人去面试工程师职位,通不过面试是应该的。(假设如描述所说最难只问到二叉树。) 我反对面试官随便网上找一道题就拿来问的做法,我也...

算法题关于真分数符合条件的分式已经整出来了 正在写排序,==先 //打印符合条件的分式 public void print(int n) { int count =0; for (int m = 0; m <= n; m++) { for (int j = 1; j <= n; j...

算法题。紧急。只需要思路因为是编程解决,所以应该设计好数据结构去遍历, 最差结果是二分法的(坐9个人,顺序是13-1-25-7-19-4-10-16-22,前三个可交换) 最好结果是隔一位坐一个,共13个人,当然这是不可能出现的...

推荐阅读
图文推荐
栏目列表