Moore's voting algorithm

最近在刷LeetCode的题的时候,遇到这样一个问题:从一个数组中找出出现半数以上的元素。
通过查资料发现可以通过Moore’s voting algorithm来完美解决。

算法的思想

每次都找出一对不同的元素,从数组中删掉,直到数组为空或只有一种元素。 不难证明,如果存在元素e出现频率超过半数,那么数组中最后剩下的就只有e。
当然,最后剩下的元素也可能并没有出现半数以上。比如说数组是[1, 2, 3],最后剩下的3显然只出现了1次,并不到半数。所以得到结果后,需要与原始数组进行比对进行验证

算法的实现

在算法执行过程中,我们使用常量空间实时记录一个候选元素a以及其出现次数count,a即为当前阶段出现次数超过半数的元素。
在遍历开始之前,该元素a为空,count=0。
然后在遍历数组A时,如果f(c)为0,表示当前并没有候选元素,也就是说之前的遍历过程中并没有找到超过半数的元素。那么,如果超过半数的元素c存在,那么c在剩下的子数组中,出现次数也一定超过半数。因此我们可以将原始问题转化为它的子问题。此时c赋值为当前元素, 同时f(c)=1。
如果当前元素A[i] == a, 那么++count。(没有找到不同元素,只需要把相同元素累计起来)
如果当前元素A[i] != a,那么–count。 (相当于删除1个c),不对A[i]做任何处理(相当于删除A[i])
如果遍历结束之后,count不为0,那么元素a即为寻找的元素。上述算法的时间复杂度为O(n),而由于并不需要真的删除数组元素,我们也并不需要额外的空间来保存原始数组,空间复杂度为O(1)。

代码实例

/**********************************************************
*Filename:MooreVoting.c
*Author:Liusuo Chen
*Data:2015-8-9
*Description:寻找超过半数的元素
**********************************************************/
#include <stdio.h>

/**********************************************************
*function:MooreVoting
*describe:寻找超过半数的元素
**********************************************************/
int MooreVoting(int array[],int n)
{
    int i,ArrId = 0,count = 1;
    for(i=1;i<n;++i){
        array[i] = array[ArrId]? ++count:--count;
        if(!count){
            ArrId = i;
            count = 1;
        }
    }
    return array[ArrId];
}

/**********************************************************
*Function:judge
*Description:判断结果是否符合
**********************************************************/
void judge(int array[],int n,int num)
{
    int i,count=0;
    for(i=0;i<n;++i){
        if(array[i] == num) ++count;
    }
    if(count > 0){
        printf("The number is %d\n",num);
    }else{
        printf("none\n");
    }
}

int main(void)
{
    int result;
    int array[10]={1,1,1,5,6,2,1,1,1,1};
    result = MooreVoting(array,10);
    judge(array,10,result);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值