• 出现次数超过一半的数字


    题目

      数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为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对应的数字则为符合题目要求的数字。

    more_half_num函数的作用是:1.如果数组中有超过出现次数超过数组长度一半的数字,返回该数字2.否则返回最有一个元素,所以最后要用check_more_than_half该函数检测返回的元素的个数是否超过函数的一半长度。

    class Solution {
    public:
        int MoreThanHalfNum_Solution(vector<int> num) {
            if(num.size()==1)
                return num[0];
    
            int count=1;
            int flag=num[0];
            for(int i=1;i<num.size();++i)
            {
                if(flag==num[i])
                    ++count;
                else
                {
                    if(count>=1)
                        --count;
                    else
                    {
                        count=0;
                        flag=num[i];
                    }
                }
            }
            return count>=1?flag: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;
    }

     

  • 相关阅读:
    安卓基础干货(六):安卓Activity的学习
    安卓基础干货(四):安卓网络编程的学习
    安卓基础干货(三):安卓数据库的学习
    安卓基础干货(二):安卓测试以及解析
    Broadcast 源码笔记
    使用smb 将vm Ubuntu磁盘 挂载到windwos
    libbinder -- BinderService
    Android属性系统
    AndroidO -- 背光手动调节流程
    Typora+PicGo-Core+gitee实现上传服务
  • 原文地址:https://www.cnblogs.com/tianzeng/p/10226697.html
Copyright © 2020-2023  润新知