第二十一章:数组中超过出现次数超过一半的数字

第二十一章数组中出现次数超过一半的数字

题目:数组中有一个数字出现的次数超过了数组长度的一半,找出这个数字。 


//题目:数组中有一个数字出现的次数超过了数组长度的一半,找出这个数字。 
#include <iostream>  
#include <vector>
#include <hash_map>  
  
using namespace std;  
 

//第一种方法
//hash法,时间O(n),空间O(n)
int Find(int *a,int N){
	hash_map<int,int> hm;
	int candidate;
	int maxTimes=INT_MIN;
	for(int i=0;i<N;i++){
		hm[a[i]]++;
		if(hm[a[i]]>maxTimes){
			maxTimes=hm[a[i]];
			candidate=a[i];
		}
	}
	return candidate;
}

//第二种方法
//统计法,时间O(n),空间O(1)
int Find2(int *a, int N)  //a代表数组,N代表数组长度  
{  
    int candidate;  
    int nTimes, i;  
    for(i = nTimes = 0; i < N; i++)  
    {  
        if(nTimes == 0)  
        {  
            candidate = a[i], nTimes = 1;  
        }  
        else  
        {  
            if(candidate == a[i])  
                nTimes++;  
            else  
                nTimes--;  
        }  
    }  
    return candidate;   
}  

//第三种方法
//删除法,因为涉及到删除,数组不好操作,所以用容器处理
int Find3(int *a,int N)  //a代表数组,N代表数组长度  
{  
	vector<int> num(a,a+N);
	for(auto it=num.begin();it!=num.end();){
		auto n=next(it);
		for(;n!=num.end()&&n==it;++n);
		if(n==num.end())break;
		num.erase(n);
		it=num.erase(it);
	}
	return *num.begin();
}  
int main()  
{  
	int a[]={4,5,6,5,5,4,7,5,5};
	cout<<Find3(a,sizeof(a)/sizeof(int))<<endl;
}  

加强版水王:找出出现次数刚好是一半的数字


//题目:找出出现次数刚好是一半的数字 
#include <iostream>  
#include <vector>
#include <hash_map>  
  
using namespace std;  
 

//第一种方法
//统计法,时间O(n),空间O(1)
//将不看数组的最后一个元素,先将问题转化成了超过一半的数处理
//最后一个元素无外乎两种情况,一种是最后一个元素不是这等于一半的数,那就不予考虑,以上得出的即是答案
//最后一个元素即是这等于一半的数,上面得出的就不一定是解,那就统计该元素出现的次数
int Find(int *a, int N)  //a代表数组,N代表数组长度  
{  
    int candidate;  
    int nTimes, i;  
    for(i = nTimes = 0; i < N; i++)  
    {  
        if(nTimes == 0)  
        {  
            candidate = a[i], nTimes = 1;  
        }  
        else  
        {  
            if(candidate == a[i])  
                nTimes++;  
            else  
                nTimes--;  
        }  
    }  
	int cnt=0;
	for(int i=0;i<N;i++)
		if(a[i]==candidate)cnt++;
    return cnt==N/2?candidate:a[N-1];   
} 

//第二种方法
//两个变量记录法
int Find2(int *a,int N){

	int candidate1,candidate2;  
    int nTimes1, nTimes2, i;  
          
    for(i = nTimes1 = nTimes2 =0; i < N; i++)  
    {  
        if(nTimes1 == 0)  
        {  
            candidate1 = a[i], nTimes1 = 1;  
        }  
        else if(nTimes2 == 0 && candidate1 != a[i])  
        //注意:这里的判断条件加上第二个变量是否等于第一个变量的判断  
        {  
              
            candidate2 = a[i], nTimes2 = 1;  
        }  
        else  
        {  
            if(candidate1 == a[i])  
                nTimes1++;  
            else if(candidate2 == a[i])  
                nTimes2++;  
            else  
            {  
                nTimes1--;  
                nTimes2--;  
            }  
        }  
    }  
    return nTimes1>nTimes2?candidate1:candidate2;
}
int main()  
{  
	int a[]={7,5,6,5,5,7,7,5};
	cout<<Find2(a,sizeof(a)/sizeof(int))<<endl;
}  




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值