题目:
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
直接的思路就是先给数组进行排序,然后就能很容易地统计出每个数字出现的次数。
但是这种思路并没有考虑到数组的特性:数组中有一个数字出现的次数超过了数组长度的一半。如果将这个数组排序,那么排序之后位于数组中间的数字一定就是那个出现次数超过数组长度一半的数字,即中位数。
bool g_bInputInvalid=false;
//判断输入的数组是否无效
bool CheckInvalidArray(int* numbers,int length)
{
g_bInputInvalid=false;
if(numbers==NULL || length<=0)
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 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;
//Partiton:快速排序
index=Partition(numbers,length,start,end);
}
else
{
start=index+1;
index=Partition(numbers,length,start,end);
}
}
int result=numbers[middle];
if(!CheckMoreThanHalf(numbers,lengh,result))
result=0;
return result;
}
另一种思路:
数组中有一个数字出现次数超过数组长度的一半,也就是它出现的次数比其他所有数字出现的次数的和还要多。
可以考虑在遍历数组的时候保存两个值:一个数组中的数字,一个次数。
当我们遍历到下一个数字的时候,如果下一个数字和我们之前保存的数字相同,则次数加1;如果下一个数字和我们之前保存的数字不同,则次数减1.如果次数为0,则我们需要保存下一个数字,并把次数设为1。由于我们要找的数字出现的次数比其他数字出现的次数之和还要多,因此要找的数字应该是最后一次把次数设为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;
}