leetcode python3 169题/229题 摩尔投票法

169题 多数元素

找出n个元素的数组中出现次数大于n/2的元素。

属于经典简单的数组题,但是方法多,还是列举一下,顺便把摩尔投票法学习一下。

方法一:排序法。

库函数。用sort函数排序,那么中间位置一定是答案。时间复杂度为

O(nlogn),空间复杂度为O(logn)

方法二:计数法。

库函数。这个思路是最简单最不需要脑子的,但是如果直接遍历去count,时间复杂度太高会超时提交失败。但如果转化为集合,利用集合中元素唯一的性质就可以降低至少n/2的时间复杂度。可以提交成功。

但是使用库函数的我觉得都没有意义... 只能说可以作为练习理解。

方法三:哈希表。

典型的哈希思想例子,创建一个哈希表存储数组中元素出现的次数,再创建集合利用集合中元素唯一的性质遍历哈希表的key查找符合要求的value. 时间复杂度和空间复杂度都是O(n)

这个才能叫真正的算法叭,但是方法一使用排序其实也有它的思路,应该学习。

class Solution:
    def majorityElement(self, nums: List[int]) -> int:
        dict_helper = {}
        set_nums = set(nums)
        for each in nums:
            dict_helper[each] = dict_helper.get(each, 0) + 1
        for each_key in set_nums:
            if dict_helper[each_key] > len(nums)/2:
                return each_key

方法四:摩尔投票法。

思路是抵消,candidate设置为nums[0],count=0. 如果下一个值等于candidate count+=1,否则count-=1。那么当count再次为0,它的意义是前面【一段】中的众数个数为len/2,那么就可以抛过去不再考虑,重新定义candidate为下一个值,到最后count必为非负!绝妙

注意它是用来找多数元素而非众数的哈。只有有 > len/2 这个性质才能这样去用算法。

class Solution:
    def majorityElement(self, nums: List[int]) -> int:
        candidate = nums[0]
        count = 0
        for each in nums:
            if count == 0: candidate = each
            if each == candidate: count += 1
            else: count -= 1
        return candidate
            

229题 求众数2

这是摩尔投票法的一个进阶版。特地翻出来做了一下,比传统的要多检验数目 > len/3 和 cand1 = cand2 两个过程。我写出这个:

class Solution:
    def majorityElement(self, nums: List[int]) -> List[int]:
        cand1, cand2 = nums[0], nums[0]
        count1, count2 = 0, 0
        for each in nums:
            if count1 == 0: cand1 = each
            if count2 == 0: cand2 = each
            count1 += 1 if cand1 == each else -1
            count2 += 1 if cand2 == each else -1
        #与传统摩尔投票法的区别是这里需要检验每个数是否超过n/3个
        count1 = count2 = 0
        for each in nums:
            if each == cand1: count1 += 1 
            if each == cand2: count2 += 1 
        res = [i for i,c in zip((cand1, cand2), (count1, count2)) if c > len(nums)/3]
        return list(set(res)) #保证不重复

没提交我就发现了盲点:这样cand1和cand2不就完完全全一样嘛??怎么可以找得到不相等的两个众数... 发现问题出现在我写的if判断是分离的,其实应该赋值给一个之后就直接结束,这里的逻辑判断不可分离!否则就会cand12完全同步

另外这里还要强调一点:不分离的逻辑判断也意味着cand12不相撞,count1+1时count2不会-1

class Solution:
    def majorityElement(self, nums: List[int]) -> List[int]:
        cand1, cand2 = nums[0], nums[0]
        count1, count2 = 0, 0
        for each in nums:
            if cand1 == each: count1 += 1
            elif cand2 == each: count2 += 1
            elif not count1: cand1, count1 = each, 1
            elif not count2: cand2, count2 = each, 1
            else:
                count1 -= 1
                count2 -= 1
        #与传统摩尔投票法的区别是这里需要检验每个数是否超过n/3个
        count1 = count2 = 0
        for each in nums:
            if each == cand1: count1 += 1 
            if each == cand2: count2 += 1 
        res = [i for i,c in zip((cand1, cand2), (count1, count2)) if c > len(nums)/3]
        return list(set(res)) #保证不重复

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值