题目描述
题干:
给定一个大小为 n 的整数数组,找出其中所有出现超过 ⌊ n/3 ⌋ 次的元素。
示例 1:
输入:[3,2,3]
输出:[3]
示例 2:
输入:nums = [1]
输出:[1]
示例 3:
输入:[1,1,1,3,3,2,2,2]
输出:[1,2]
题解思路
返回所有满足条件的众数,首先想到的就是遍历得到每个元素的个数然后统计
用哈希表存储每个元素出现的次数,然后统计出现个数大于 n/3 的元素返回
这里说一说这里用到的第二种方法,叫摩尔投票法,也叫多数投票法
传统的方式就是两个人进行选举采取的常用方式,核心思想是抵消和计数
因为我们都默认统计第一个元素为标准,从1开始,每次遇到相同元素则加一
遇到不同的元素相当于抵消掉自己一票,而当自己为个数为0的时候也就丧失了竞争力
这个时候就切换到下一个竞选者,这里是两个人竞争的结果,因为题目是大于 n/3
所以我们要对此方法进行升级一下,一次统计两个元素的票数,其他不变
正确代码
// 哈希表
public List<Integer> majorityElement(int[] nums) {
HashMap<Integer, Integer> hashMap = new HashMap<>();
// 遍历数组获取每个数字出现的次数
for (int num : nums) {
if (hashMap.containsKey(num)) {
hashMap.put(num, hashMap.get(num) + 1);
} else {
hashMap.put(num, 1);
}
}
// 找到众数
List<Integer> ansList = new ArrayList<>();
for (Integer integer : hashMap.keySet()) {
if (hashMap.get(integer) > (nums.length / 3)) {
ansList.add(integer);
}
}
return ansList;
}
// 摩尔投票法(plus版本)
public List<Integer> majorityElement01(int[] nums) {
int element1 = 0;
int element2 = 0;
int vote1 = 0;
int vote2 = 0;
for (int num : nums) {
if (vote1 > 0 && num == element1) {
vote1++;
} else if (vote2 > 0 && num == element2) {
vote2++;
} else if (vote1 == 0) {
element1 = num;
vote1++;
} else if(vote2 == 0) {
element2 = num;
vote2++;
} else {
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> ansList = new ArrayList<>();
if (vote1 > 0 && cnt1 > (nums.length /3)) {
ansList.add(element1);
}
if (vote2 > 0 && cnt2 > (nums.length /3)) {
ansList.add(element2);
}
return ansList;
}
总结
这里其实如果使用哈希表方法就是简单问题,不过摩尔计数法的思路确实可以用到很多方面
这个思路核心的思路就是对拼消耗,针对不同的标准来达成满足条件的元素
如果文章存在问题或者有更好的题解,欢迎在评论区斧正和评论,各自努力,你我最高处见