leetcode-169 Majority Element(Moore's voting algorithm)

最近在刷LeetCode的题(169 Majority Element)的时候,发现一个特别巧妙的算法:Moore's voting algorithm

这个算法是解决这样一个问题:从一个数组中找出出现半数以上的元素。

Moore的主页上有这个算法的介绍:A Linear Time Majority Vote Algorithm和这个算法的一个简单示例演示:演示链接

算法的基本思想

每次都找出一对不同的元素,从数组中删掉,直到数组为空或只有一种元素。 不难证明,如果存在元素e出现频率超过半数,那么数组中最后剩下的就只有e。

As we sweep we maintain a pair consisting of a current candidate and a counter. Initially, the current candidate is unknown and the counter is 0.

When we move the pointer forward over an element e:

  • If the counter is 0, we set the current candidate to e and we set the counter to 1.
  • If the counter is not 0, we increment or decrement the counter according to whether e is the current candidate.
When we are done, the current candidate is the majority element,if there is a majority.

当然,最后剩下的元素也可能并没有出现半数以上。比如说数组是[1, 2, 3],最后剩下的3显然只出现了1次,并不到半数。排除这种false positive情况的方法也很简单,只要保存下原始数组,最后扫描一遍验证一下就可以了。

(But if you must confirm that the chosen element is indeed the majority element, you must take one more linear pass through the data to do it.)

算法的实现

在算法执行过程中,我们使用常量空间实时记录一个候选元素c以及其出现次数f(c),c即为当前阶段出现次数超过半数的元素。

在遍历开始之前,该元素c为空,f(c)=0。

然后在遍历数组A时,如果f(c)为0,表示当前并没有候选元素,也就是说之前的遍历过程中并没有找到超过半数的元素。那么,如果超过半数的元素c存在,那么c在剩下的子数组中,出现次数也一定超过半数。因此我们可以将原始问题转化为它的子问题。此时c赋值为当前元素, 同时f(c)=1。

如果当前元素A[i] == c, 那么f(c) += 1。(没有找到不同元素,只需要把相同元素累计起来)

如果当前元素A[i] != c,那么f(c) -= 1。 (相当于删除1个c),不对A[i]做任何处理(相当于删除A[i])

如果遍历结束之后,f(c)不为0,那么元素c即为寻找的元素。上述算法的时间复杂度为O(n),而由于并不需要真的删除数组元素,我们也并不需要额外的空间来保存原始数组,空间复杂度为O(1)。

C++代码实现如下:

int majorityElement(vector<int> &num)
{
    int curIdx = 0, count = 1;
    for (int i = 1; i < num.size(); ++i)
    {
        num[i] == num[curIdx] ? ++count : --count;
        if (!count)
        {
            curIdx = i;
            count = 1;
        }
    }

    return num[curIdx];
}
我的C语言实现:
int majorityElement(int num[], int n) {
    int vote = num[0];
    int count = 1;
    int i;
    for(i = 1; i < n; i++){
        vote == num[i] ? count++ : count--;
        if(count == 0){
            vote = num[i];
            count = 1;
        }
    }
    return vote;
}

 
  
转自:http://blog.csdn.net/chfe007/article/details/42919017


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值