数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如,输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。
思路:如果这个数组是排序的话,那么数组中间的那个数字就是答案,此时效率O(nlogn)。显然,不可能那么简单。我们现在要得到的就转换为求数组中位数,那么依据快排的思想,取一个数字,大于它的放右边,小于它的放左边,如果这个数字位于数组左边,那么中位数则在数字右边,反之,则在左边,然后继续处理,直到求得中位数。
代码如下:
int MoreThanHalfNum(int* numbers,int length)
{
if(CheckInvalidArray(numbers,length))
return 0;
int middle=length>>1;
int start=0;
int end=length-1;
int index=Partition(numbers,length,start,end);
while(index!=middle)
{
if(index>middle)
{
end=index-1;
index=Partition(numbers,length,start,end);
}
else
{
start=index+1;
index=Partition(numbers,length,start,end);
}
}
int result=numbers[middle];
if(!CheckMoreThanHalf(numbers,length,result))
result=0;
return result;
}
bool g_bInputInvalid=false;
bool CHeckInvalidArray(int* numbers,int length)
{
g_bInputInvalid=false;
if(numbers==nullptr||length<=0)
g_bInputInvalid=true;
return g_bInputInvalid=true;
return g_bInputInvalid;
}
bool CheckMoreThanHalf(int* numbers,int length,int number)
{
int times=0;
for(int i=0;i<length;i++)
{
if(numbers[i]==number)
times++;
}
bool isMoreThanHalf=true;
if(times*2<=length)
{
g_bInputInvalid=true;
isMoreThanHalf=false;
}
return isMoreThanHalf;
}
还有一种方法:
存一个结果int,记录一个出现次数int,然后我们遍历数组,如果次数为0,则重置为当前值,次数设为1,否则该增增,该减减。
代码如下:
int MoreThanHalfNum(int* numbers,int length)
{
if(CheckInvalidArray(numbers,length))
return 0;
int result=numbers[0];
int times=1;
for(int i=1;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;
}