面试题集锦

1、给定N张扑克牌和一个随机函数,设计一个洗牌算法

假定N=54,首先,我们有一个随机函数发生器,能够产生1-54之间的随机数,如何保证抽第一张牌是54中可能,抽第二张牌是53中可能,……
可以这样做,假设扑克牌是一个54维的数组card, 我们要做的就是从这个数组中随机取一个元素,然后在剩下的元素里再随机取一个元素… 这里涉及到一个问题,就是每次取完元素后,我们就不会让这个元素参与下一次的选取。
我们要实现的目的是以等概率的方式将这54个数随机打乱排列,因此,可以这样处理:
第一次抽牌在初始54张牌中,将 随机产生的牌x,与第一个元素互换,
第二次抽牌在剩下的53张牌中,将 随机产生的牌y,与第二个元素互换。。。

public void RandomShuffle(int a[], int n){ 
    for(int i=0; i<n; i++){ 
        int j = rand() % (n-i) + i;// 产生i到n-1间的随机数 
        Swap(a[i], a[j]);//交换位置 
    } 
}

2、n条直线最多能将一个平面分成多少部分?

num[n] = num[n – 1] + n
思路:第n条直线总能和前⾯面n-1条直线形成n-1个交点,将第n条直线 分成n份,每一份会多分出一个平⾯面;num[n] = 1 + n*(n+1)/2=1+1+2+3+4+…N;

3、n个平面最多能将一个空间切成多少部分?

显然,当这n个平面满足以下条件时,所分割的部分数是最多的。 1、 这n个平面两两相交; 2、 没有三个以上的平面交于一点; 3、 这n个平面的交线任两条都不平行。 对于一般情况一下子不易考虑,我们不妨试着从简单的,特殊的情况入手来寻找规律。设n个 平面分空间的部分数为 an,易知 当n=1时,an=2 ; 当n=2时,an=4 当n=3时,an=8 当n=4 时,情况有些复杂,我们以一个四面体为模型来观察,可知an=15 ; 从以上几种情况,很难找出一个一般性的规律,而且当n的值继续增大时,情况更复杂,看来这样不行。那么,我们把问题在进一步简单化,将空间问题退化到平面问题:n条直线最多可将平面分割成多少个部分?由上题可知,即n条直线最多可将平面分割成1/2*(n^2+n+2) 个部分。

现在,我们回到原问题,用刚才的思路来解决空间的问题,设k个平面将空间分割成a(k)个部分,再添加上第k+1个平面,这个平面与前k个平面相交有k条交线,这k条交线,任意三条不共点,任意两条不平行,因此这第k+1个平面就被这k条直线分割成b(k)个部分。 而这b(k)个部分平面中的每一个,都把它所通过的那一部分空间分割成两个较小的空间。所以,添加上这第k+1个平面后就把原有的空间数增加了b(k)个部分。由此的递推关系式 a(k+1)=a(k)+b(k)
推导可知,n个平面最多可将平面分割成 =(n^3+5*n+6)/6

4、两个软硬程度一样的鸡蛋,它们在某一层摔下会碎,有个100层的建筑,要求最多用两个鸡蛋确 定鸡蛋安全下落的临界位置,给出临界位置?如果是n层楼,m个鸡蛋,请给出确定临界位置的算法?

这是典型的动态规划问题。假设f[n]表示从n层楼找到摔鸡蛋不碎安全位置的最少判断次数。假设第一个鸡蛋第一次从第i层扔下,如果碎了,就剩一个鸡蛋,为确定下面楼层中的安全位置,必须从第一层挨着试,还需要i-1次;如果不碎的话,上面还有n-i层,剩下两个鸡蛋,还需要f[n-i]次(子问题,实体n层楼的上n-i层需要的最少判断次数和实体n-i层楼需要的最少判断次数其实是一样的)。因此,最坏情况下还需要判断max(i-1,f[n-i])次。

状态转移方程:f[n] = min{ 1 + max(i – 1 ,f[n – i]) | i = 1 ..n }
初始条件: f[ 0 ] = 0 (或f[ 1 ] = 1 )

现在推广成n层楼,m个鸡蛋:
还是动态规划。假设f[n,m]表示n层楼、m个鸡蛋时找到摔鸡蛋不碎的最少判断次数。则一个鸡蛋从第i层扔下,如果碎了,还剩m-1个鸡蛋,为确定下面楼层中的安全位置,还需要f[i-1,m-1]次(子问题);不碎的话,上面还有n-i层,还需要f[n-i,m]次(子问题,实体n层楼的上n-i层需要的最少判断次数和实体n-i层楼需要的最少判断次数其实是一样的)。

状态转移方程:f[n,m] = min{ 1 + max(f[i – 1 ,m – 1 ], f[n – i,m]) | i= 1 ..n }
初始条件:f[i, 0 ] = 0 (或f[i, 1 ] = i),对所有i

5、n个人,只有1个人是明星,明星所有人都认识,但明星不认识其他任何人,如何找到该明星?如果n很大很大,如果改进你的算法?

线性扫描一遍,两两比较,每次比较都会排出一个人:若a认识b,则a一定不是明星;若a不认 识b,则b一定不是明星;n很大的情况下可以采用分布式方法,每个机器处理一部分数据,最后每个 机器选出一个候选,归并

点赞