229. 求众数 II-摩尔投票法

248 篇文章 2 订阅
232 篇文章 0 订阅

一、题目描述

给定一个大小为 n 的整数数组,找出其中所有出现超过 ⌊ n/3 ⌋ 次的元素。

示例 1:
输入:[3,2,3]
输出:[3]
示例 2:
输入:nums = [1]
输出:[1]
示例 3:
输入:[1,1,1,3,3,2,2,2]
输出:[1,2]

二、解题

摩尔投票法

这题是169题的改进题目。一个是大于N/2的众数,一个是大于N/3的众数。由于是大于N/3,所以众数的数量会超过两个。
这里复制力扣底下评论比较有意思的比喻:多方混战

首先要知道,在任何数组中,出现次数大于该数组长度1/3的值最多只有两个。

我们把这道题比作一场多方混战,战斗结果一定只有最多两个阵营幸存,其他阵营被歼灭。数组中的数字即代表某士兵所在的阵营。

我们维护两个潜在幸存阵营A和B。我们遍历数组,如果遇到了属于A或者属于B的士兵,则把士兵加入A或B队伍中,该队伍人数加一。继续遍历。

如果遇到了一个士兵既不属于A阵营,也不属于B阵营,这时有两种情况:

  • A阵营和B阵营都还有活着的士兵,那么进行一次厮杀,参与厮杀的三个士兵全部阵亡:A阵营的一个士兵阵亡,B阵营的一个士兵阵亡,这个不知道从哪个阵营来的士兵也阵亡。继续遍历。

  • A阵营或B阵营已经没有士兵了。这个阵营暂时从地球上消失了。那么把当前遍历到的新士兵算作新的潜在幸存阵营,这个新阵营只有他一个人。继续遍历。

大战结束,最后A和B阵营就是初始人数最多的阵营。判断一下A,B的人数是否超过所有人数的三分之一就行了。

如果用候选人的方法去理解感觉没这种混战的想法有意思好理解。

class Solution {
    public List<Integer> majorityElement(int[] nums) {
        //同样使用摩尔投票法
        //这题是超过⌊ n/3 ⌋次的元素,所以最多只有两个这种元素。
        //维护两个候选人,
        int canNum1 = nums[0],canNum2 = nums[0];
        int cnt1 = 0,cnt2 = 0;
        List<Integer> list = new ArrayList<>();
        for(int num : nums){
            //当前数据等于一个候选人时,继续
            if(num == canNum1){
                cnt1++;
                continue;
            }
            if(num == canNum2){
                cnt2++;
                continue;
            }
            //如果第一个候选人配对
            if(cnt1 == 0){
                //更新候选人
                canNum1 = num;
                cnt1 = 1;
                continue;
            }
            //如果第二个候选人配对
            if(cnt2 == 0){
                //更新候选人
                canNum2 = num;
                cnt2 = 1;
                continue;
            }
            //如果当前值并没有配对
            cnt1--;
            cnt2--;
        }
        //重新统计候选人的数量是否大于N/3;
        cnt1 = 0;
        cnt2 = 0;
        for(int num : nums){
            if(canNum1 == num){
                cnt1++;
            }else if(canNum2 == num){
                cnt2++;
            }
        } 
        //判断是否大于N/3;
        if(cnt1>nums.length/3){
            list.add(canNum1);
        }
        if(cnt2>nums.length/3){
            list.add(canNum2);
        }
        return list;
    }
}
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、付费专栏及课程。

余额充值