229. 求众数 II 证明

为什么不可能最多有3个floor(n/3)次数的数?
设n = 3i + k, 其中k = 0, 1, 2
如果要超过floor(n/3)(我们简称代表数, 下同), 次数至少为i+1, 有三个这样的数, 则需要大小为3(i+1)=3i+3 > k, 所以不可能有三个这样的数.

由此可以类推, 如果n = 3i 或 3i + 1, 最多有一个这样的数, 如果n = 3i + 2, 最多有两个这样的数. 不过这个结论也不太用得上啦~

然后搜到网上的答案是这样写的, 你可能会奇怪, 为什么这个算法是正确的? 两个候选人是怎么回事? 这是因为它跳过了很多证明步骤.

class Solution(object):
    def majorityElement(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        candidate1 = [0, 0]
        candidate2 = [0, 0]
        for n in nums:
            if n == candidate1[0]:
                candidate1[1] += 1
            elif n == candidate2[0]:
                candidate2[1] += 1
            elif candidate1[1] == 0:
                candidate1 = [n, 1]
            elif candidate2[1] == 0:
                candidate2 = [n, 1]
            else:
                candidate1[1] -= 1
                candidate2[1] -= 1
            
        return [x for x in set([candidate1[0], candidate2[0]]) if nums.count(x) > len(nums)/3]

首选in我们要证明一下, 每次从数组中去掉3个不同的数, 则在剩下的数里, 那些代表数依然不变

设n = 3i + k, 其中k = 0, 1, 2. 代表数至少有i+1个次数. 去掉3个不同的数后, 剩下n=3i + k - 3 = 3(i-1) + k个数.
由于所有数中, 最多有2个代表数, 所以被除去的那三个不同的数字中, 至多有两个代表数, 那么在剩下的数中, 每个代表数最多被除掉了1个次数, 所以至少还有(i + 1)- 1 = i个, 在剩余的3(i-1)+k个数中依然是代表数(定理1)
所以上面代码的candidate1candidate2是在维护两个不同的数字, 关键在于:

else:
	candidate1[1] -= 1
	candidate2[1] -= 1

当遇到的新数与维护的两个数字不同时, 将它们三个一并除去由于定理1, 原代表数在剩下的数中依然是代表数.

最后代表数一定会留在剩下来的两个候选数中, 对它们依次调用nums.count数次数即可(O(n)时间复杂度).

return [x for x in set([candidate1[0], candidate2[0]]) if nums.count(x) > len(nums)/3]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值