求一个数组中出现次数超过n/3的数(c++实现)

题目要求如下:

令A是一个长度为n的正整数序列。试设计一个时间
和空间复杂度分别为O(n)和O(1) 的算法,判断A中
是否存在这样的元素x,x在序列中出现次数超过n/3。
若存在这样的x,则将其输出。

实现思路:

BM(Boyer-Moore Majority Vote Algorithm)投票法:设置一个计数器,在遍历数组的时候,如果是这个数,则计数器加1,否则减1,该方法用来计数超过一半的数非常方便。在这里我们改进一下BM投票计数法:设置两个计数器,如果是两个数中的一个,则对应的计数器加1,如果不是这两个数中的任何一个,则两个计数器都减1。如果计数器为0了,则统计当前这个数。那么如果一个数出现次数超过1/3,则最后必然出现在统计的数中,但是我们不确定得到的这两个数出现次数是否超过1/3,因此最后需要验证一下。该算法的时间复杂度是O(n),空间复杂度是O(1)。

证明思路:

求数组中多于一半的或者是多于1/3的全部数字都可以用这种方法解决

这里给你一个数组,要你求出所有出现数量多于 ⌊ n/3 ⌋的数字,这题方法简单,但是原理非常复杂,,首先用两个数a,b,n1,n2来分别记录峰1,峰2,峰1的数量,峰2的数量,可以证明,当求 所有多于⌊ n/m ⌋的数的时候,只要定义(m-1)个不同的数字,以及(m-1)个不同的计数,将所有计数初始化为0,所有数字初始化为不同值,记住,一定要是不同值,但是可以是任何值,要不然不能保证计算过程中所有数字的不同,最后可能导致result里面添加多个相同的数字

证明方法是,当发现num[i]和a1,a2,…am-1里面一个数字相同的时候,假设是ak,将nk加一,当发现num[i]和任何一个数字都不同的时候,替换掉任何一个nk==0的数字,也就是ak=num[i],nk++,就这样一直计算下去,可以证明,当计算完成的时候,a1,a2…am-1里面一定存在所有出现次数多于⌊ n/m ⌋的数,这时只要重新检查a1,a2…am-1看那个出现的次数多于⌊ n/m ⌋就行了

这里简单的证明一下,假设有m个区间,每个区间有t个数,那么n可表示成n=m*t+z,这里z=0~m-1,这里假设有一组多于⌊ n/m ⌋,设这组为A,那么他的数量num(A)>=t+1,<=n,可以证明,每一个A里面的数可以和m-1个其他数消除,每m-1个其他数可以消除一个A,我们现在来证明当算法进行到最后A一定消除不完。

我们使A的数量最少,为t+1,非A的数尽可能的多,为(m-1)*t+m-1-1=n-t-1,非A的数能消耗A的数最多为⌊ (m-1)*t+m-1-1 ⌋=⌊ t-1/(m-1) ⌋<t+1,因此A的数最后一定有剩,A的数有剩则其一定存在于a1,a2…am-1里面,否则其一定被消耗完了,这和假设不符,其他各个多于⌊ n/m ⌋的数也可以同样证明,

代码:

class Solution {
public:
    vector<int> majorityElement(vector<int>& nums) {
        int a=0;
        int b=1;
        int ca=0;
        int cb=0;
        for(int i=0;i<nums.size();i++)
        {
            if(nums[i]==a)
                ca++;
            else if(nums[i]==b)
                cb++;
            else if(ca==0)
            {
                a=nums[i];
                ca++;
            }
            else if(cb==0)
            {
                b=nums[i];
                cb++;
            }
            else
            {
                ca--;
                cb--;
            }
        }
        ca=0;
        cb=0;
        for(int i=0;i<nums.size();i++)
        {
            if(nums[i]==a)
                ca++;
            else if(nums[i]==b)
                cb++;
        }
        vector<int> result;
        if(ca>nums.size()/3)
            result.push_back(a);
        if(cb>nums.size()/3)
            result.push_back(b);
        return result;
    }
};

猜你喜欢

转载自blog.csdn.net/weixin_41106545/article/details/83213354
今日推荐