一些摩尔投票法的思考和理解

leetcode169 和229可以参考一下

贴一下自己的leetcode229的代码

class Solution:
    def majorityElement(self, nums: List[int]) -> List[int]:
        dic = {}
        for num in nums:
            if num in dic:
                dic[num]+=1                    
            else:
                if len(dic)<2:
                    dic[num] = 1
                else:
                    for key in list(dic):
                        dic[key]-=1
                        if dic[key]==0:
                            del dic[key]             
        return [key for key in dic if nums.count(key)>len(nums)//3]

摩尔投票法基本的介绍以及适用的情况我就不多说了,一般的博客讲这个方法的时候都是讲找主数(出现次数大于n//2),这里我就不多说了,那如果是找主数(出现次数大于n//3)呢?我们拓展一下这个方法。

形象的理解一下这个方法,其实我们可以把这种方法理解成一个选举的过程,上台的人的个数取决于主数的定义,如果是大于n//2,那么结果就是最多只有一个人上台,如果是n//3,那么结果就是最多有两个人上台

以n//3定义的主数举例:最多可能有两个主数,因此我们设置两个候选人的位置,那么投票过程中会有以下几种情况:

  1. 台上刚开始有两名真正的候选人(两个真正的主数)在这种情况下,他们两个肯定会坚持到最后,因为他们的票数都要大于假的候选人的票数。
  2. 两名假候选人上台。 在这种情况下,肯定会成为第三种情况,一定有一个假的候选人被轰下台(除非不存在真的候选人,如果是这种情况,最后鉴别的时候会去掉) 
  3. 台上两个候选人一真一假,如果只有一个候选人是真命天子,那么最后鉴别阶段我们把假的候选人去掉;如果有两个真命天子,那么台上站的假的候选人一定会被台下的真的踢下台,但是真的依然会在台上

    最后我们得到的候选人中一定包括最多两个真命天子,最后我们做一轮鉴别,得到真正的主数字,整个复杂度是Cn,也就是O(n)

接下来我们来说上述情况下的关键点和细节,找出主数字的关键点依然是主数出现的次数比其他非主数出现的次数多,这意味着我们拼票的时候只要拼主数和非主数的票,不拼主数之间的票的话,最后一定可以得到正确的结果,所以情况1的时候,一定可以得到最后正确的结果,但是,台上一真一假的时候,我们不知道谁真谁假,所以台下的真的和台上的真的依然存在拼票的情况,但是,台上存在的另一个假的候选人此时不会和台上存在的另一个真的拼票,弥补了两个真的拼票的情况下,台上的真的候选人票数减少的情况,因此最后所有真的候选人必定都会上台。

中间有个point,也就是当台上的一个候选人count==0的时候,不是立刻让他下台,而是等待下一轮的投票,看下一轮是否有机会复活,这个点其实很多时候理解不透彻的话,很容易写错,关键点还是一定要理解清楚主数出现的次数一定大于n//3

这样的话,可以尝试将这个概念推广到解决n//4,n//5等等的情况。

如有错误,烦请指正

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值