出现次数超过一半的数字

Posted tianzeng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了出现次数超过一半的数字相关的知识,希望对你有一定的参考价值。

题目

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

思路 

  1. 数组中出现次数超过一半,所以数组中间的数字一定就是那个出现次数超过数组一半的数字
  2. 基于快排算法中的Partition函数,使得比选中的数字小的数字都在它左边,比选中的数字大的数字都在它的右边
  3. 如果选中的数字的下标刚好是n/2,那么这个数字就是数组中的中位数
  4. 如果它的下标大于n/2,那么中位数应该位于它的左边,继续在左边寻找
  5. 如果它的下标小于n/2,那么中位数应该位于它的右边,继续在右边寻找
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

class Solution
{
    public:
        int more_half_num(vector<int> &v);
        int partition(vector<int> &v,int start,int end);
        bool check_more_than_half(vector<int> &v,int num);
        bool check_valid(vector<int> &v);
};
int Solution::more_half_num(vector<int> &v)
{
    if(!check_valid(v))
        return 0x3f3f;
    
    int mid=v.size()>>1;
    int start=0;
    int end=v.size()-1;
    int index=partition(v,start,end);
    while(index!=mid)
    {
        if(index>mid)
            index=partition(v,start,index-1);
        else
            index=partition(v,index+1,end);
    }
    int result=v[mid];
    if(check_more_than_half(v,result))
        return result;
    return 0x3f3f;
}
bool Solution::check_more_than_half(vector<int> &v,int num)
{
    int count=0;
    for(auto k:v)
    {
        if(k==num)
            ++count;
    }
    if(count<<1<v.size())
        return false;
    return true;
    
}
int Solution::partition(vector<int> &v,int start,int end)
{
    if(v.empty()||v.size()<=0||start<0||end>=v.size())
    {
        cerr<<"invalid parameter"<<endl;
        return -1;
    }
    
    int t=v[start];
    while(start<end)
    {
        while(start<end&&t<=v[end])
            --end;
        if(start<end)
            v[start++]=v[end];
            
        while(start<end&&t>v[start])
            ++start;
        if(start<end)
            v[end--]=v[start];
    }
    v[start]=t;
    return start;
}
bool Solution::check_valid(vector<int> &v)
{
    if(v.empty()||v.size()<0)
        return false;
    return true;
}
int main()
{
    vector<int> v{1,2,3,6,6,6,6,6,5};
    Solution s;
    int t=s.more_half_num(v);
    if(t!=0x3f3f)
        cout<<t<<endl;
    return 0;
}

  数组中出现次数超过一半,所以该数字出现的次数超过数组长度的一半,也就是它出现的次数比其他所有数字出现次数的和还要多;遍历数组的时候保存两个值:一个是数字,一个是次数。如果下一个数字和保存的数字相同,则次数加1;不相同则减1;如果次数为0,则保存下一个数字,次数设置为1。因为数字超过一半,所以最后一次数字大于1对应的数字则为符合题目要求的数字。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

class Solution
{
    public:
        int more_half_num(vector<int> &v);
        bool check_more_than_half(vector<int> &v,int num);
        bool check_valid(vector<int> &v);
};
int Solution::more_half_num(vector<int> &v)
{
    if(!check_valid(v))
        return 0x3f3f;
    
    int result=v[0];
    int count=1;
    for(int i=1;i<v.size();++i)
    {
        if(count==0)
        {
            result=v[i];
            count=1;
        }
        else if(result==v[i])//如果记录的值与统计值相等,记数值增加
            ++count;
        else//如果不相同就减少,相互抵消
            --count;
    }
    
    if(check_more_than_half(v,result))
        return result;
    return 0x3f3f;
}
bool Solution::check_more_than_half(vector<int> &v,int num)
{
    int count=0;
    for(auto k:v)
    {
        if(k==num)
            ++count;
    }
    if(count<<1<v.size())
        return false;
    return true;
    
}
bool Solution::check_valid(vector<int> &v)
{
    if(v.empty()||v.size()<0)
        return false;
    return true;
}
int main()
{
    vector<int> v{6,1,1,6,2,6,3,6,6,5};
    Solution s;
    int t=s.more_half_num(v);
    if(t!=0x3f3f)
        cout<<t<<endl;
    return 0;
}

 三

  定义一个栈,先把数组的第一个元素入栈

  1. 如果下一个元素与栈顶元素相同,下一个元素入栈
  2. 否则,栈顶元素出栈
  3. 如果最后栈不为空,栈顶元素就是重复超过一半的数字(而且最后栈中的元素的个数就是此元素超过其它元素个数总和的数)
#include <iostream>
#include <stack>
#include <vector>
using namespace std;

class Solution
{
    public:
        int more_half_num(vector<int> &v);
};
int Solution::more_half_num(vector<int> &v)
{
    if(v.empty()||v.size()<0)
        return 0x3f3f;
        
    stack<int> s;
    s.push(v[0]);
    for(int i=1;i<v.size();++i)
    {
        if(!s.empty())
        {
            if(s.top()==v[i])
                s.push(v[i]);
            else
                s.pop();
        }
        else
            s.push(v[i]);
    }
    if(!s.empty())
        return s.top();
    return 0x3f3f;
}
int main()
{
    vector<int> v{1,2,3,6,6,6,6,6,5};
    Solution s;
    int t=s.more_half_num(v);
    if(t!=0x3f3f)
        cout<<t<<endl;
    return 0;
}

 

 

以上是关于出现次数超过一半的数字的主要内容,如果未能解决你的问题,请参考以下文章

Java 剑指offer(39) 数组中出现次数超过一半的数字

剑指 Offer 39. 数组中出现次数超过一半的数字 的 详细题解

数组中出现次数超过一半的数字(C语言+Java)

出现次数超过一半的数字

剑指 Offer 39. 数组中出现次数超过一半的数字

找出数组中出现次数超过一半的数字