记我的第一次视频面试

来源:互联网 发布:linux 图形界面 编辑:程序博客网 时间:2024/04/28 08:13

  最近参加一个据说是创业公司的视频面试,其中波折趣味一言难尽,在此分享一下我做的两道算法类题目这是其中一道,初看这道题,第一感觉是只要考虑每个数的个位即可,因为只有个位上的乘法才有可能产生0,于是乎好办了,每隔10个数能产生一个10的倍数,个位上的1……9又能产生一个0,于是只要算出有多少个10即可,每隔十个数能产生2个0,再看看m%10是否大于5,如果大于5,也能产生一个0,好,问题似乎是解决了,有点想当然了,写程序验证,验证当m = 20正确;m = 25时,按照我的算法,结果应该是2 * 25/10 + 1 = 5,但是看了一下,25!结尾是有6个0,不对,哪出了问题了呢?原来在于25这里,25可以分解为5*5,而20后的21,22,23,24,25五个数的个位为:1,2,3,4,5,只能产1个0,但是21,22,23,24,25这五个数相乘是能产生两个0的,原因就在于25这里,5*5,原来,0的产生其实是跟5有关的,从1开始,每隔5个数,能产生一个0,因为每隔5个数,就能产生一个因子5,比如1……5,有一个5,6……10,10=2 * 5,那是不是结果就是m/5呢,还是不,当m=25时还是不对,这是怎么回事?因为到25这里,产生了2个5,那125是5*5*5,625 = 5*5*5*5要把这些情况都考虑进去才对,也就是每隔5的一个幂次级,就多产生一个5,比如到25这里,要多一个5,也就是说每隔25,就多产生一个5(如50,75,100)也就会多产生一个0,125这里会多产生一个0……这下问题理清楚了,可以写程序了。

int count = 0;for (int i = 5; i <= m; i *= 5){count += m / i;}

道题的时间复杂度为Log5(m),看起来也挺靠谱的,像是一个算法的时间复杂度,嘿嘿,验证也无误。写程序也就是这么一点点,但是想的过程却是曲曲折折的简约而不简单

再来看看另外一道,我认为更难了。


也就是比如一个35矩阵:

                                              1 2 3 4 5       1 1 1

                                              1 2 3 4 5 => 2 2 2

                                               1 2 3 4 5       3 3 3

                                                                    4 4 4

                                                                    5 5 5

在一维数组中是按照[1 2 3 4 5 1 2 3 4 5 1 2 3 4 5]存的,现在要将它转置,那么它在数组中应该是:[1 1 1 2 2 2 3 3 3 4 4 4 5 5 5],当年到这道时,真是有点犯难,按以前求二维数组的矩阵来转置得了,多省事,非得弄这么一茬,不好弄了,想了好久没什么进展,直到最后才发现了一点点眉目:不是要转置么,我一个一个移,先将原矩阵的第0(按照C语言中的习惯,从0开始)列的第1个1保存,然后将它之前的5,4,3,2后移一位,再将1插入到数组的第1个位置,一维数组变成:11 2 3 4 5 2 3 4 5 1 2 3 4 5按这个方法,移另个一个1,数组变成:1 1 12 3 4 5 2 3 4 5
2 3 4 5,好了,转置后的第一行完成了,原来当我进行移位的时候,数组中的其它元素的相对位置是不变的。再看数组中,因为1 已经排好序,不用管了,剩下3组2 3 4 5 ,怎么办呢,对了,把2 3 4 5 2 3 4 5 2 3 4 5 当成是一个新3的行4列矩阵,像刚才一样进行移位变换,于是数组变成:1 1 1 2 2 2 3 4 5 3 4 5 3 4 5,好了, 1、2都排好序了,剩下3组3 4 5 3 4 5 3 4 5,依此类推,结果就出来了。于是我们可以看到,对于m*n行的矩阵,把转置分为n - 1轮,每轮过后就会完成一列的转置,当完成n-1轮后,原矩阵已经有n-1列完成了转置,最后列由于算法的设计,自动转置了。照这个算法,交换的次数就要多了,但是可以实现空间复杂度为O(1),也算是满足要求了。想起来有点点复杂,贴程序,用Python写的

#-*-coding:utf8-*-  #a:数组,m:行,n:列  def fun(a,m,n):      #这个运算需要进行的次数      for c in range(n - 1):#表示[0,n-1)          #每次的起始位置          frm = c * m          for i in range(1,m):              '''''下一个要确定位置的元素位置,并保存其值,             每次运算过后 ,剩下的元素组成的的m行数组列数减1             '''              pos = i * (n - c) + frm              temp = a[pos]              #pos的前n-1个数整体前移一位              for j in range(pos - 1,frm + i -1,-1):                  a[j + 1] = a[j]              #找到位置并赋值              a[frm + i] = temp  #测试           a = [1,1,1,1,1,2,2,2,2,2,3,3,3,3,3]  b = [1,1,2,2,3,3,4,4,5,5,6,6,7,7]  c = [1,1,1,2,2,2,3,3,3]  fun(a,3,5)  fun(b,7,2)  fun(c,3,3)  print a,'\n',b,'\n',c

这个算法想的时候很不顺利,写程序的时候到也有点小小的波折所以想记录自己在解这两道题的时候思维过程,通过建立清晰的思维模型,严谨的分析与验证,才能得出正确的答案,在解题的过程中,如何想的真的很重要,它反映了我平时的一些不好的思维习惯,这些习惯定势还有很多地方需要改进。其实在视频面试的时候由于网络不太好,我完全有机会作弊,但是我知道,看到答案时那一声惊呼:“原来是这样“,对我来说没有任何作用,只有自己慢慢想出来的经历了这个思维过程,至少对自己是有用的,还好,面试那人比较耐心,也比较相信我,嘿嘿大笑



原创粉丝点击