题目描述:
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。

思路1:建立Hash表,统计各个数字出现的次数。空间复杂度O(n),时间复杂度O(n)

class Solution {
public:
int MoreThanHalfNum_Solution(vector<int> numbers) {
if(numbers.size()==0)
return 0;
int n=numbers.size();
//超过半数,需要>n/2
vector<int> count(n+1,0);
for(int i=0;i<n;i++){
count[numbers[i]]++;
}
for(int i=0;i<=n;i++){//需要遍历所有的数字
if(count[i]>n/2)
return i;
}
return 0;
}
};

思路2:如果存在某个数字的个数超过数组长度的一半,则该数字出现的次数一定比其他数字出现的次数和还要多,所以可以用两个变量分别存储数字和次数。如果下一个数字和当前res一样,则计数++,否则计数–。如果计数==0了,则重新用下一个数字对res和计数进行初始化,最后返回的res即为要求的结果

class Solution {
public:
int MoreThanHalfNum_Solution(vector<int> numbers) {
if(numbers.size()==0)
return 0;
int res=numbers[0];
int times=1;
for(int i=1;i<numbers.size();i++){
if(times==0){
res=numbers[i];
times=1;
}
if(numbers[i]==res)
times++;
else
times--;
}
if(!CheckMoreThanHalf(numbers,res))
return 0;
return res;
}
bool CheckMoreThanHalf(vector<int> numbers,int res){
int length=numbers.size();
int count=0;
for(int i=0;i<length;i++){
if(res==numbers[i])
count++;
}
if(count*2>numbers.size())
return true;
return false;
}
};

思路3:使用快速排序的思想,如果存在某个数的个数>n/2,则这个数一定是排序后数组的中位数

class Solution {
public:
int MoreThanHalfNum_Solution(vector<int> numbers) {
int length=numbers.size();
if(length==0)
return 0;
int mid=length>>1;
int start=0;
int end=length-1;
int pivot=Partition(numbers,length,start,end);
//中间位置不是枢轴点的位置
while(pivot!=mid){
if(pivot>mid){
end=pivot-1;
pivot=Partition(numbers,length,start,end);
}else{
start=pivot+1;
pivot=Partition(numbers,length,start,end);
}
}
int res=numbers[mid];
if(!CheckMoreThanHalf(numbers,length,res))
return 0;
return res;
}
bool CheckMoreThanHalf(vector<int> &numbers,int length,int res){
int times=0;
for(int i=0;i<length;i++){
if(numbers[i]==res)
times++;
}
bool isMoreThanHalf=true;
if(times*2<=length)
isMoreThanHalf=false;
return isMoreThanHalf;
}
int Partition(vector<int>& numbers,int length,int start,int end){
int pivot_index=rand()%(end-start+1)+start;
int pivot=numbers[pivot_index];
numbers[pivot_index]=numbers[start];
while(start<end){
while(start<end&&pivot<numbers[end])
end--;
numbers[start]=numbers[end];
while(start<end&&pivot>numbers[start])
start++;
numbers[end]=numbers[start];
}
numbers[start]=pivot;
return start;
}
};