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

Posted hequnwang10

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了229. 求众数 II-摩尔投票法相关的知识,希望对你有一定的参考价值。

一、题目描述

给定一个大小为 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;
    

以上是关于229. 求众数 II-摩尔投票法的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode 453. 最小操作次数使数组元素相等 / 66. 加一 / 229. 求众数 II(摩尔投票法)

Leetcode 229.求众数II

229 Majority Element II 求众数 II

[E摩尔投票] lc169. 多数元素(多数投票算法+经典)

快乐水题229. 求众数 II

快乐水题229. 求众数 II