题目:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
例如:输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。
由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
解法1:基于Partition函数的时间复杂度为O(n)的算法
思路:在排序后因为数组中有一个数字超过长度的一半,也就是说这个数字就是统计学上的中位数,即长度为n的数组中第n/2大的数字。
随机快速排序
#include<iostream>
using namespace std;
bool g_bInputInvaild=false;
//检查输入的有效性
bool CheckInValidArray(int* numbers,int length){
g_bInputInvaild=false;
if(numbers==nullptr||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 Partition(int data[],int length,int start,int end){
if(data==nullptr||length<=0||start<0||end>=length)
throw new srd::exception("Invalid Parameters");
int index=RandomInRange(start,end);
Swap(&data[index],&data[end]);
int small=start-1;
for(index=start;index<end;++index){
if(data[index]<data[end]){
++small;
if(small!=index)
Swap(&data[index],&data[small]);
}
}
++small;
Swap(&data[small],&data[end]);
return small;
}
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;
}
解法2:根据数组特点找出时间复杂度为O(n)的算法
思路: 我们可以考虑在遍历数组时候保存两个值:一个是数组中的一个数字;另一个是次数
当我们遍历到下一个数字的时候:1.如果下一个数字和我们之前保存的数字相同,则次数加1
2.如果下一个数字和我们之前保存的数字不相同,则次数减1
3.如果次数为0,那么我们要保存下一个数字,并把次数设置为1
结果:由于要找的数字出现的次数比其他所有数字出现的次数之和还要多,那么要找的数字一定是times大于等于1的时候那个结果
#include<iostream>
using namespace std;
bool g_bInputInvaild=false;
//检查输入的有效性
bool CheckInValidArray(int* numbers,int length){
g_bInputInvaild=false;
if(numbers==nullptr||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 result=numbers[0];
int times=1;
//
for(int i=1;i<length;i++){
//如果次数等于0的时候 保存后一个数字
//要找的数字肯定是result里保存的数字
if(times==0){
result=numbers[i];
times=1;
}
//如果下一个数字和之前保存的数字相同,次数加1
else if(numbers[i]==result)
times++;
//如果下一个数字和之前保存的数字不同,次数减一
else
times--;
}
if(!CheckMoreThanHalf(numbers,length,result))
result=0;
return result;
}