用“打架”来理解摩尔投票法,生动形象一看就懂

本文通过“打架”来形象解释摩尔投票法,当人数m和王座n不同时,如何确定能坐上王座的阵营。通过具体的例子和伪代码,阐述了摩尔投票法在解决寻找出现次数大于1/n * m次的数组元素问题中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

用“打架”来理解摩尔投票法,生动形象一看就懂

1.问题提出

摩尔投票法,最简单形象的理解,就是一群人去抢座位。

在某个战乱年代,有m个来自不同阵营的人,要去争抢n个王座,大家都想抢,怎么办呢,那肯定是谁的人多,谁就可以坐上王座呗。比如只有1个王座的话,那人数必须要大于总人数一半(1 / 2)的阵营才可以坐,否则其他阵营的人联合起来就可以把你搞死;有2个王座的话,那人数必须要大于总人数的 (1/3)的两个阵营可以坐,有n个王座,那阵营人数必须大于m * (1 / n)。

那么这个问题抽象化就是:如何从一个长度为m的数组中,找到出现次数大于(1 / n) * m次的数?

2.一个王座(n = 2)

A A B C B A A

假设现在有如上7个人来自A B C三个阵营,要抢一个王座,那么按照顺序:

  • 首先是A,一来发现王座是空的,那他就坐上去,此时王座属于A阵营

  • 下一个又是A,发现自家已经占了王座了,针不戳,于是王座的A阵营人员+1

  • 然后是B,发现座位上有人了,那不行,得打一架,于是跟一个A打了一架,两个人同归于尽了,不过王座上还有一个A

  • 接下来是C,发现座位上有人了,那不行,得打一架,于是跟一个A打了一架,两个人同归于尽了,这个时候王座就空了

  • 然后又是B,发现王座是空的,就坐上去

  • 然后又依次来了两个A,过程略。

所以最后占有王座的,就是A阵营了。伪代码如下:

int num = 0;//王座是谁家的
int count = 0;//王座上的人数
for(int i : nums){
	if(count == 0) num = i;//王座是空的 i坐上去

    if(num == i) count++;//i阵营人数+1
    else count--;//打一架
}

//计数阶段略

return num;

3.两个及以上王座(n > 2)

A B B C B C A A

对于这种情况,以两个王座为例,两个以上的同理:

  • 首先A来了,两个王座都是空的,就坐到其中一个上

  • 然后来了个B,发现两个王座有一个被A占了,但是还有一个是空的,那算了,多一事不如少一事,我坐这个是一样的,于是B坐在另一个王座上

  • 然后又来了个B,看到B阵营已经占据了一个王座,赶紧加入了进去

  • 这个时候来了个C,看到两个王座都有人了,很生气,要跟AB打一架,于是A派一个人,B派一个人,这三个人同归于尽了。那么这个时候原本A坐的王座就空出来了

哎,有同学可能会问了,为啥A和B都要派一个人跟C打?C去抢A的,B在旁边看戏不行么?其实不是的。考虑一下如果只有A B C三个人,两个位置,A和B先坐了,这个时候A和B是处于一种投票的平衡状态,你一半我一半嘛。但是如果C来了,这种平衡就被打破了,变成了每个人占1/3,那两个位置谁能坐呢?谁都不能坐,所以这时候这三个人就只能同归于尽。也就是说,C的加入对A和B的影响是同时产生的,会打破A和B原本的投票平衡状态,A阵营和B阵营为了维持自己的状态,都得派一个人出来,然后和新来的C中和掉。

  • 接着来了B,于是加入到B的王座
  • 然后又来了个C,看到有个王座是空的,好,然后他就坐了上去,这个时候两个王座分别由B阵营(2人)和C阵营(1人)占有
  • 然后来了个AA B C三家又打了一架C的王座空了
  • 最后来了个A,坐到了空的王座上。

因此,最后由A阵营B阵营拿下这两个王座。伪代码如下:

int num1 = 0, num2 = 0;//两个王座
int count1 = 0, count2 = 0;//都是空的

for(int i : nums){
    if(i == num1)//哟 我家已经占了第一个王座了
        count1++;
    else if(i == num2)//我家虽然没占到第一个,但是占到了第二个
        count2++;
    else if (count1 == 0){//有一个王座是空的
        num1 = i;
        count1 = 1;
    }else if(count2 == 0){//另一个王座是空的
        num2 = i;
        count2 = 1;
    }else{//打一架
        count1--;
        count2--;
    }
}

//计数阶段略

其他

摩尔投票还有一个计数阶段,不过这个比较简单,我这里就不讲了。n = 2时的摩尔投票看代码还算好理解,但是当n > 2时,很多同学就看不太懂了(包括我一开始也没看懂)。不过后来我把抽象问题具体化,一下就想通了,因此写了这篇博文记录一下。最后希望大家在生活中和平相处,不要打架

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值