面试题:29数组中出现超过一半的数字
题目:数组中有一个数字出现次数超过数组长度一半的数字,请找出这个数字。
分析:首先题目给出了这个题目的假设条件,就是存在这样的一个数字。那么我的想法是先排序然后找第n/2数就是所要找的数字,排序里面速度最快的也就是快速排序,那么应用快速排序对数组进行排序然后再通过下标找到所要的结果。
int MoreThanHalfNum (int* numbers, int length)
{
if( CheckInvalidArray (numbers, length))
return 0;
middle=length >> l;//使用移位运算代替除法运算
start=0;
int end=length -l;
int index=QuickSort(numbers, length, start, end);
while (index!=middle)
{
if (index>middle)
{
end=index - 1;
index=<span style="font-family: Arial, Helvetica, sans-serif;">QuickSort</span><span style="font-family: Arial, Helvetica, sans-serif;">(numberse length, start, end);</span>
}
else
{
start=index+1;
index=<span style="font-family: Arial, Helvetica, sans-serif;">QuickSort</span><span style="font-family: Arial, Helvetica, sans-serif;">(numbers, length, start, end);</span>
}
}
int result=numbers [middle];
if(! CheckMoreThanHalf( numbers, length, result))
result=0;
return result;
}
其中CheckMoreThanHalf是验证的方法,没写出实际的实习,书上说是体现思考全面的做法。但是从这道题目中我感到很多东西,第一:细节,基本上所有的题目中都会通过一些小的不能再小的代码来判断一个程序员的严谨性,比如用移位运算代替除法运算,用引用传递代替值传递以防止多个实例时复制值而产生的中间变量浪费时间、空间。但是这些细节要多些代码才能慢慢的注意。第二:思路的问题,不知道为什么到了这一章的题目,我想到的答案往往只能是基本合格的水平,如果再加上一些考虑不严谨和细节问题基本上就是不及格的水平,为啥最佳答案想不起来
本题的最佳答案是:最佳答案自己实在没想到实在是没脸说是自己写的代码,所以是抄的书上的。
接下来我们从另外一个角度来解决这个问题。数组中有一个数字出现的次数超过数组长度的一半,也就是说它出现的次数比其他所有数字出现次数的和还要多。因此我们可以考虑在遍历数组的时候保存两个值:一个是数组中的一个数字,一个是次数。当我们遍历到下一个数字的时候,如果下一个数字和我们之前保存的数字相同,则次数加1;如果下一个数字和我们之前保存的数字不同,则次数减1,如果次数为零,我们需要保存下一个数字,并把次数设为1。由于我们要找的数字出现的次数比其他所有数字出现的次数之和还要多,那么要找的数字肯定是最后一次把次数设为1时对应的数字。
int MoreThanHalfNum (int* nurnbers, int length)
{
jf(CheckInvalidArray (numloers, length))
return 0:
int result=numbers[0];
int times=1:
for (int i=l; i<length; ++i)
{
if (times = = 0)
{
result=numbers [i];
times=1;
}
else if (numbers [i] ==result)
times++;
else
times--;
}
if(! CheckMoreThanHalf( numbers, length, result))
result=0;
return result;
}