多数元素
- 关于摩尔投票法:
候选人(cand_num)
初始化为nums[0]
,票数count
初始化为1
。
当遇到与cand_num
相同的数,则票数count = count + 1
,否则票数count = count - 1
。
当票数count
为0
时,更换候选人,并将票数count
重置为1
。
遍历完数组后,cand_num
即为最终答案。
- 为何这行得通呢?
投票法是遇到相同的则票数 + 1,遇到不同的则票数 - 1。
且“多数元素”的个数> ⌊ n/2 ⌋,其余元素的个数总和<= ⌊ n/2 ⌋。
因此“多数元素”的个数 - 其余元素的个数总和 的结果 肯定 >= 1。
这就相当于每个“多数元素”和其他元素 两两相互抵消,抵消到最后肯定还剩余至少1个“多数元素”。
所以无论数组是1 2 1 2 1,亦或是1 2 2 1 1,总能得到正确的候选人。
public class Main {
public int majorityElement(int[] nums) {
int cand_num = nums[0];
int count = 1;
for (int i = 1; i < nums.length; i++) {
if (cand_num == nums[i]) {
count++;
} else {
if (--count == 0) {
cand_num = nums[i];
count = 1;
}
}
}
return cand_num;
}
}
求众数II
大于1/3意味着最多可能有两个候选人,所以我们就假设为两个候选人进行投票
初始化从第0个人开始,没人0票
如果遇到候选人,票数+1
如果没有遇到候选人且候选人票数为0,更换候选人
如果没有遇到候选人且候选人票数不为0,所有候选人票数-1
然后再统计两个候选人的票数
如果大于1/3就当选
题解参考
关于摩尔投票的动画可以去题解看
public class Main {
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 count1 = 0, count2 = 0;
//开始投票
for (int num : nums) {
//如果是候选人1
if (num == cand1) {
count1++;
continue;
}
//如果是候选人1
if (num == cand2) {
count2++;
continue;
}
//如果不是cand1也不是cand2,判断有没有候选人还没有票,没有就换人
if (count1 == 0) {
cand1 = num;
count1++;
continue;
}
if (count2 == 0) {
cand2 = num;
count2++;
continue;
}
//如果两个候选人都还有票,就都-1
count1--;
count2--;
}
//验证票数是否满足大于1/3
count1 = 0;
count2 = 0;
for (int num : nums) {
if (cand1 == num) count1++;
else if (cand2 == num) count2++;
}
if (count1 > nums.length / 3) res.add(cand1);
if (count2 > nums.length / 3) res.add(cand2);
return res;
}
}