摩尔投票法简介

摩尔投票法


问题描述: 假设我们的数组有 nn 个元素, 我们要找到其中出现次数超过一半的元素

算法流程:

  1. 从这 nn 个元素中选一个作为 candidate,记录它的票数为 votes = 1.

  2. 此时我们的数组中还有 n−1n−1 个元素, 我们每次都取出一个元素(记为 current), 并重复执行以下的步骤(一共 n-1 次)

    1. 将它和我们当前的 candidate 做比较, 如果它们的值一样, 那么 votes++, 也就是投赞同票
    2. 如果它们的值不一样, votes--, 也就是投反对票. 如果此时 votes = 0 的话, 那么 candidate <- current, 也就是说我们让 current 成为了新的 candidate, 并记 votes = 1
  3. 最后 candidate 的值就可能是我们想要的出现次数超过一半的元素, 此时我们得再遍历一遍数组进行计数看它到底是不是

在看完上面的算法流程之后, 你可能跟我一样感到很困惑. 为什么这样最后我们就能找到出现次数超过一半的元素. 其实只要想明白一个原理就很简单

💡 出现次数超过 ⌊n/2⌋⌊n/2⌋ 次的元素如果存在, 此时数组中的其他元素一定是出现次数小于 ⌊n/2⌋⌊n/2⌋ 的

这句话有什么用呢 ?

因为摩尔投票法的做法其实就是投票

  • 可以是投赞同票, 此时相当于我们在统计这个元素出现的次数
  • 可以是投反对票. 相当于我们撤销了一个同意票, 就是抵消抵消抵消!!!

但是因为出现次数超过一半的元素加起来的票数(赞同票) > 剩下所有不是的(反对票)这件事是一定成立的, 所以无论怎样最后赢的永远是出现次数超过一半的元素. 于是我们就找到了 😃

如果还是不懂可以看看下面的这个 GIF 图理解一下~

代码


class Solution {
    public int majorityElement(int[] nums) {
        if (nums.length < 2) {
            return nums[0]; 
        }
        int candidates = nums[0];
        int votes = 1;
        // step 1. start to vote
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] != candidates) {
                votes -= 1;
                if (votes == 0) {
                    candidates = nums[i];
                    votes = 1;
                }
            } else {
                votes += 1;
            }
        }
        // step2. check
        int occurs = 0;
        for (var val: nums) {
            if (candidates == val) {
                occurs += 1;
            }
        }
        if (occurs >= nums.length / 2) {
            return candidates;
        } else {
            return -1;
        }
    }
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值