算法01 - 摩尔投票法(求众数)

引子

leetcode 169.多数元素

 

分析

1. 由于多数元素大于n / 2,所以多数元素至多一个且其一定为这个数组的众数,问题就转化成为了求一个数组的众数。

2. 求数组众数,为了使时间复杂度为O(n),我们可以很快想到空间复杂度O(n)的算法一:可以使用一个hash table来存储。

3. 为了降低空间复杂度为O(logn),我们也可以想到时间复杂度为O(nlogn)的排序算法二:先排序,结果中n / 2 就是众数。

3. 但是本题设置了空间复杂度为O(1),这样限定我们只能用有限的储存空间,这样我们也可以很快想到基于位运算的算法三:每一位计算一次为1的个数,如果大于n / 2就说明众数在这里为1,反之,为0,最后就可以拼接出结果。

4. 但是本题最优解是摩尔投票法。

 

摩尔投票法原理(简述)

最简单的理解:让数组中的数组进行厮杀,最后剩下的一定是众数。

 

算法步骤:

1. 两个变量,candidate记录候选众数,初始化为null,cnt记录厮杀结果初始化为0。

2. 从0 - n-1 开始遍历,如果cnt为0,表示candidate厮杀结束,需要将当前位置设置为candidate。

3. 最后剩下的candidate一定是众数。

 

算法原理:

详见:https://blog.csdn.net/happyeveryday62/article/details/104136295

证明:

假设共有n个代表(一人一票,选票总数为n)。当onwaier看到第i个代表的选票时( 1 ≤ i ≤ n ) (1 \leq i \leq n)(1≤i≤n),前面他已经看到的所有选票可以分为两组,第一组是k个代表赞同cand;另一组是选票可以全部成对(选票不同)抵销。当处理完所有的选票时,如果存在大多数,则cand当选。
假设存在一个x其不同于cand,但拥有的选票超过n / 2 n/2n/2。但因为第二组的选票可以全部成对抵销,所以x最多的选票数为( n − k ) / 2 (n - k) / 2(n−k)/2,因此x必须要收到第一组的选票才能超过一半,但是第一组的选票都是cand的,出现矛盾,假设不成立。
所以,如果存在大多数,cand就是那个。(注:如果不存在,cand不一定是众数。)
————————————————
版权声明:本文为CSDN博主「Onwaier」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/happyeveryday62/article/details/104136295

 

适用范围:

如果至多选一个代表,那他的票数至少要超过一半(⌊ 1/2 ⌋)的票数;

如果至多选两个代表,那他们的票数至少要超过 ⌊ 1/3 ⌋ 的票数;

如果至多选m个代表,那他们的票数至少要超过 ⌊ 1/(m+1) ⌋ 的票数。

 

题解:

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int cnt = 0, now = nums[0];
        for (int i = 0; i < nums.size(); i++){
            if(cnt == 0) now = nums[i];
            if(now == nums[i]) cnt++;
            else cnt--;
        }
        return now;
    }
};

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Boyer-Moore投票是一种用于查找元素序列中的众数的算法,它具有线性时间复杂度和常数级空间复杂度。该算法由Robert S. Boyer和J Strother Moore命名,是一种典型的流算法。\[1\] Boyer-Moore投票分为两个阶段:抵消阶段和计数阶段。在抵消阶段,两个不同的候选人进行对抗,并同时抵消各自的一张票。如果两个候选人相同,则累加可抵消的次数。在计数阶段,如果抵消阶段最后得到的抵消计数不为0,那么这个候选人有可能超过一半的票数。为了验证这一点,需要遍历一次元素序列,统计票数,才能确定最终的众数。\[2\] 更多关于Boyer-Moore投票的详细信息可以参考\[3\]。 #### 引用[.reference_title] - *1* *3* [投票算法](https://blog.csdn.net/qq_17550379/article/details/83818965)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [尔(Boyer-Moore)投票](https://blog.csdn.net/qq_40692109/article/details/104805815)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值