找出数组中大于出现频率大于n/2的数
方法一:hashmap,排序等,这种常规思路就不概述
方法二:摩尔投票
不同的两数相互抵消,最后剩下的肯定是多于一半的那个数。当count为0时,选举当前为最多的数,并++,不为选举最多的数的使count–。最终一定是candidate是最多的数,但条件是出现频率必须大于数组长度的一半。
public int majorityElement(int[] nums) {
int count = 0;
Integer candidate = null;
for (int num : nums) {
if (count == 0) {
candidate = num;
}
count += (num == candidate) ? 1 : -1;
}
return candidate;
}
给定一个大小为 n 的整数数组,找出其中所有出现超过n/3 次的数
记录两个众数,最后再遍历一遍这两个众数。
public List<Integer> majorityElement(int[] nums) {
List<Integer> res = new ArrayList<>();
if (nums == null || nums.length == 0) {
return res;
}
// 定义两个候选者和它们的票数
int cand1 = 0,cand2 = 0;
int cnt1 = 0, cnt2 = 0;
// 投票过程
for (int num : nums) {
// 如果是候选者1,票数++
if (num == cand1) {
cnt1++;
// 一遍遍历,如果你不想写continue,你写多个else if也可以
continue;
}
// 如果是候选者2,票数++
if (num == cand2) {
cnt2++;
continue;
}
// 既不是cand1也不是cand2,如果cnt1为0,那它就去做cand1
if (cnt1 == 0) {
cand1 = num;
cnt1++;
continue;
}
// 如果cand1的数量不为0但是cand2的数量为0,那他就去做cand2
if (cnt2 == 0) {
cand2 = num;
cnt2++;
continue;
}
// 如果cand1和cand2的数量都不为0,那就都-1
cnt1--;
cnt2--;
}
// 检查两个票数符不符合
cnt1 = cnt2 = 0;
for (int num : nums) {
if (num == cand1) {
cnt1++;
} else if (num == cand2) {
// 这里一定要用else if
// 因为可能出现[0,0,0]这种用例,导致两个cand是一样的,写两个if结果就变为[0,0]了
cnt2++;
}
}
int n = nums.length;
if (cnt1 > n / 3) {
res.add(cand1);
}
if (cnt2 > n / 3) {
res.add(cand2);
}
return res;
}