摩尔投票算法

 摩尔投票算法

 顾名思义是一种类似投票过程的算法

其由1981年出版的Robert S. Boyer和J Strother Moore的名字命名,并且是流式算法的典型例子。


LeedCode原题:

给定一个大小为 的数组,找到其中的众数。众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。

你可以假设数组是非空的,并且给定的数组总是存在众数。


易知事实:由于假定总是存在众数,那么每个数组有且仅有一个众数

证明假设存在两个众数,且每个出现次数都大于 ⌊ n/2 ⌋ ,那么元素个数将超过n,不符合已知条件。因此有且仅有一个众数

基于此事实:

摩尔投票算法每次从序列里选择两个不相同的数字删除掉(或称为“抵消”),最后剩下一个数字或几个相同的数字,就是出现次数大于总数一半的那个。(众数个数大于其他各种元素个数,故最后剩下一个或几个相同的数字为众数)

同时证明最终不会一个数字都不剩:

无论n为奇数还是偶数,众数的个数总是比其他元素的总和多1,无论如何消除,最后不会为空。


那么具体如何求一个数组的众数呢?参考知乎

按常理我们队数组中每种元素进行出现次数的统计,超过 ⌊ n/2 ⌋的元素则为众数。

然而其核心就是对拼消耗

类似玩一个诸侯争霸的游戏,假设你方人口超过总人口一半以上,并且能保证每个人口出去干仗都能一对一同归于尽。

最后还有人活下来的国家就是胜利。

因此不断地从数组中删除两个不同的元素,最后剩下来的一定是众数。


那么众数在数组中的顺序是否影响结果呢?答案是不会影响。

将元素的个数多少理解为打架拼人头的优势,前面删除的元素类似于已经互殴被打死了,对后面的战斗不增加优势。因此主要看拼到最后谁还有人头优势。即为众数。人多势重。

解答:

int majorityElement(int* nums, int numsSize){
    int major=nums[0];
    int count=1;
    for(int i=1;i<numsSize;i++)
    {   
        if(count==0)
            major=nums[i];
        if(nums[i]==major)
            count++;
        else
            count--;
    }
    return major;
}

摩尔投票算法的改进

给定一个整型数组,找到所有主元素,它在数组中的出现次数严格大于数组元素个数的三分之一。

算法:每次删除三个不相同的数,最后留下的一定是出现次数超过1/3的数,这个思想可以推广到出现次数超过1/k次的元素有哪些。

因为出现次数大于n/3的元素最多只有两个,所以最开始可以维护两个数字(num1,num2)和两个计数器(counter1,counter2);
遍历数组,当数组中元素和num1或者num2相同,对应的counter1或者counter2加1;
如果counter1或counter2为0,将遍历到的该元素赋给num1或者nums2;
否则counter1和counter2都减1。
 

原文地址:https://www.cnblogs.com/zhichao-yan/p/13368510.html