明确一点就是众数最多只能有2个,如果两个数出现的次数分别为a和b,a>n/ 3
,b>n/3
,这两个数为众数,设其他数字的出现次数为c,那么a+b+c=n
,有a+b>2n/3
,c<n/3
,因此最多只能有两个众数。
我们每次移除3个不同的数,因为a和b都大于c,a-c
以及b-c
都大于0,最后剩下的就一定是众数。
但是众数有可能是0个或者1个,因此为了确认选出来的两个数是否是众数,还要进行一次遍历确认其出现次数是否大于n/3
class Solution {
public List<Integer> majorityElement(int[] nums) {
int cand1 = 0, cnt1 = 0;
int cand2 = 0, cnt2 = 0;
for(int num : nums){
if(num == cand1){
cnt1++;
continue;
}
if(num == cand2){
cnt2++;
continue;
}
// 更换候选1
if(cnt1 == 0){
cand1 = num;
cnt1 = 1;
continue;
}
// 更换候选2
if(cnt2 == 0){
cand2 = num;
cnt2 = 1;
continue;
}
// 同时移除一个cand1、cand2和num
cnt1--;
cnt2--;
}
// 还需一次遍历判断候选是否为众数
cnt1 = cnt2 = 0;
List<Integer> list = new ArrayList<>();
for(int num : nums){
if(num == cand1){
cnt1++;
}else if(num == cand2){
cnt2++;
}
}
if(cnt1 > nums.length / 3)
list.add(cand1);
if(cnt2 > nums.length / 3)
list.add(cand2);
return list;
}
}