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(摩尔投票法)
229 Majority Element II 求众数 II