偶然在网上看到了人人校园招聘的两道笔试题:
1、给定一个有序数组a,长度为len,和一个数X,判断A数组里面是否存在两个数,他们的和为X,bool judge(int *a, int len, int x),存在返回true,不存在返回false
2、给定有n个数的数组a,其中超过一半的数为一个定值,在不进行排序、不开设额外数组的情况下,以最高效的算法找到这个数:int find(int *a, int n)
题目甚是眼熟,个人认为都是算法导论的书后练习题。
其中,第1题是算法导论2.3-7的原题(这里的算法不是最优,对于已排序的数组有O(n)的算法),并且题目中给出的数组a已经排序了,所以省去了2.3-7中排序的环节。
第2题是算法导论4-6的变形,算法描述为:成对比较a中的元素,如果两个一样则将此数值作为元素放在数组中,不一样的剔除出数组,这样当数组中的元素都一样时,得到的就是那个数。代码需要一个指针,指向每次插入数值的位置,每次递归调用find,通过指针与a的差计算n作为参数。
int find(int *a, int n)
{
int *pos;
int i;
int len;
pos = a;
if (1 == n)//递归停止条件
{
return a[1];
}
for (i=0; i+1 < n; i+=2)//相等的元素存入数组
{
if (a[i] == a[i+1])
{
*pos = a[i];
pos++;
}
}
len = pos - a;
if ((n%2 != 0) && (0 == len%2))//处理n是奇数且一次递归后剩余元素数为偶数的情况
{
*pos = a[n];
len += 1;
}
return find(a, len);
}
因为D(n)=O(n),C(n)=O(1),所以递归式为T(n)=T(n/2)+O(n),所以算法的时间复杂度为O(n)。
find没有验证,仅供参考