给定一个大小为 n 的整数数组,找出其中所有出现超过 ⌊ n/3 ⌋
次的元素。
示例 1:
输入:[3,2,3] 输出:[3]
示例 2:
输入:nums = [1] 输出:[1]
示例 3:
输入:[1,1,1,3,3,2,2,2] 输出:[1,2]
最简单的思路,通过比较出现次数和长度的三分之一来进行筛选,而次数统计的方法可以参考昨天那题力扣官方给的方法,也就是利用hashmap进行统计。
public static List<Integer> majorityElement(int[] nums) {
int Length=nums.length/3;
Map<Integer,Integer> Account=new HashMap<>();
List<Integer> list=new ArrayList<>();
for (int num:nums){Account.put(num,Account.getOrDefault(num,0)+1);}
for (Map.Entry<Integer,Integer> entry:Account.entrySet()){
int num=entry.getKey(),occ=entry.getValue();
if (occ>Length){
list.add(num);
}
}
return list;
}
再给一个官方的解法
摩尔投票法。
通过数学模型确定能达到目标的元素最多只有两个,因此我们设置两个未知量用来承装符合条件的数字。
public List<Integer> majorityElement(int[] nums) {
int element1 = 0;
int element2 = 0;
int vote1 = 0;
int vote2 = 0;
for (int num : nums) {
if (vote1 > 0 && num == element1) { //如果该元素为第一个元素,则计数加1
vote1++;
} else if (vote2 > 0 && num == element2) { //如果该元素为第二个元素,则计数加1
vote2++;
} else if (vote1 == 0) { // 选择第一个元素
element1 = num;
vote1++;
} else if (vote2 == 0) { // 选择第二个元素
element2 = num;
vote2++;
} else { //如果三个元素均不相同,则相互抵消1次
vote1--;
vote2--;
}
}
int cnt1 = 0;
int cnt2 = 0;
for (int num : nums) {
if (vote1 > 0 && num == element1) {
cnt1++;
}
if (vote2 > 0 && num == element2) {
cnt2++;
}
}
// 检测元素出现的次数是否满足要求
List<Integer> ans = new ArrayList<>();
if (vote1 > 0 && cnt1 > nums.length / 3) {
ans.add(element1);
}
if (vote2 > 0 && cnt2 > nums.length / 3) {
ans.add(element2);
}
return ans;
}