摩尔投票法

这篇博客介绍了如何使用摩尔投票法在O(n)时间和常数空间内找到数组中的多数元素。首先讲解了基本的多数元素问题,然后扩展到寻找出现次数超过数组长度三分之一的众数。算法通过维护几个可能的多数元素及其计数,逐步消除非众数,最后返回满足条件的众数。
摘要由CSDN通过智能技术生成

例:169. 多数元素 - 力扣(LeetCode) (leetcode-cn.com)

题目:找出一个数组中出现次数超过一半的数字。

摩尔投票法可以使用 O(n) 的时间复杂度和常数的空间解决这个问题。

把出现次数超过一半的数字定义为多数元素

首先维护一个变量,和它的票数,假设它就是答案,遍历数组,如果当前的数和维护的值相同,就为它的票数加一,否则减一,当票数减到0的时候就更新这个变量为当前值,在保证存在多数元素的情况下,遍历到最后时剩下的数一定为这个数组中多数元素。

这个算法的原理可以看作每次取出两个不同的数消掉,最后剩下的自然就是多数元素。

int n = nums.size() , t = nums[0] , cnt = 1;
for(int i =1;i<n;i++)
{
    if(nums[i]==t)cnt++;
    else cnt--;
    if(cnt==0)t = nums[i],cnt = 1;
}

进阶:229. 求众数 II - 力扣(LeetCode) (leetcode-cn.com)

找出一个数组中所有出现次数超过 ⌊ n/3 ⌋ 的数字。

和上面的类似,出现次数超过 ⌊ n/3 ⌋ 的数字最多为两个,,所以变为维护两个数即可,要注意在之后检查一遍是否满足以及是否相等。

索性直接写一个:⌊ n/(k+1) ⌋ 版本的

vector<int> majorityElement(vector<int>& nums)
{
    int t[3], cnt[3] = { 0 };
    int k = 2;
    for (int i = 1; i <= k; i++)
        t[i] = 1e9 + 1;
    bool f;
    for (int x : nums)
    {
        f = true;
        for (int i = 1; i <= k; i++)
        {
            if (x == t[i])
            {
                cnt[i]++;
                f = false;
                break;
            }
        }
        if (f)
        {
            f = true;
            for (int i = 1; i <= k; i++)
            {
                if (cnt[i] == 0)
                {
                    f = false;
                    t[i] = x;
                    cnt[i] = 1;
                    break;
                }
            }
            if (f)
            {
                for (int& xx : cnt)
                {
                    xx--;
                }
            }
        }
    }
    vector<int> ans;
    memset(cnt, 0, sizeof cnt);
    for (int x : nums)
    {
        for (int i = 1; i <= k; i++)
        {
            if (x == t[i])
                cnt[i]++;
        }
    }
    for (int i = 1; i <= k; i++)
    {
        if (cnt[i] > nums.size() / (k + 1))
            ans.push_back(t[i]);
    }
    return ans;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值