Moore's voting algorithm

来源:互联网 发布:淘宝的芦荟胶是真的吗 编辑:程序博客网 时间:2024/05/23 18:12

leetcode上有一个算法题,求数组中出现一半以上的元素。
利用Moore’s voting algorithm可以方便地解决,算法介绍页面给出了解释。

实例

如下序列:
A A A C C B B C C C B C C
^
?:0
具体步骤见执行步骤

具体算法

  我们将从上面显示的指针位置开始扫描序列。
  当我们扫描时,我们利用两个参数:现在的候选元素,以及计数器。最初,目前的候选元素未知,且计数器为0.
  当我们将指针向前移动一个元素e:
  如果计数器为0,则将当前候选元素设为e,并将计数器设为1.
  如果计数器不为0,则根据e是否为当前候选元素:

    - 如果e==候选元素,则计数器加1;
    - 如果e!=候选元素,则计数器减1;

  当我们完成后,如果数组中只有一个超过半数的元素,则候选元素即为所求。

  此算法的时间复杂度为O(n),空间复杂度为O(1)。

算法证明

  试想,如果一个序列里面有k个majority,那么就有n-k个non-majority。不妨将non-majority当作一个整体,变成同一数(并不会影响程序的正确性),那么此时序列里面就变成了两种元素。
不失一般性,不妨令第一个元素为majority(此时恰好为non-majority的元素)。那么count最多到n-k。再然后就一定是majority的元素,那么最多需要n-k个,count就会变成0,此时总共经历了2n-2k,还剩余2k-n个元素,因为k大于n/2,所以,剩余元素个数为正数,而且全为majority。
  这里用了两个假设:第一个是将所有的non-majority作为一个整体,第二个相当于是做了一个排序。

代码

  leetcode169题的具体应用

class Solution {    public int majorityElement(int[] nums) {        int cand = nums[0];        int count = 1;        for(int i = 1; i<nums.length; i++){            if(count == 0)                cand = nums[i];            if (cand == nums[i])                count++;            else                count--;        }        return cand;            }}
原创粉丝点击