LeetCode每日一题 229. 求众数 II
作者:互联网
229. 求众数 II
Tag: Array
Difficulty: Medium
Link: https://leetcode-cn.com/problems/majority-element-ii/
分析
要求一个数组中所有超过[n/3]
(向下取整)的元素,比较容易想到的是用map方法,统计每个不同元素的数量,但是本题要求用O(1)
的空间复杂度。所以这里需要一个新的方式——摩尔投票法
摩尔投票法解决的问题是,在任意多的候选人中,选出票数超过一半的的那个人。
它表明这样的规律:在任何数组中,出现次数大于该数组长度一半的值只能有1
个
假如有这样的数组表示投票 [A, B, C, A, A]
第一次遍历:抵消阶段
选择第一张票作为候选人,[A, 1]
第二张票与第一张票抵消, [A, 0]
第三张票与第一张票不同,并且计数为0,替换,[C, 1]
第四张票抵消 [C, 0]
第五张票替换 [A, 1]
最后获取A为可能的候选人
第二次遍历:计数阶段
注意如果投票是[A, B, C], 那么最后统计到[C, 1]也不能说明C的票超过半数,所以还要再遍历一次
遍历得到A的数量为3,超过半数,符合条件
那么,对于1/3:在任何数组中,出现次数大于该数组长度1/3的值最多只有2
个
对于1/3,则需要选择两个可能的候选人
推广到1/(m+1): 在任何数组中,出现次数大于该数组长度1/(m+1)的值最多只有m
个
题解
class Solution {
public List<Integer> majorityElement(int[] nums) {
// 创建返回值
List<Integer> res = new ArrayList<>();
if (nums == null || nums.length == 0) return res;
// 初始化两个候选人candidate,和他们的计票
int cand1 = nums[0], count1 = 0;
int cand2 = nums[0], count2 = 0;
// 摩尔投票法,分为两个阶段:配对阶段和计数阶段
// 配对阶段
for (int num : nums) {
// 投票
if (cand1 == num) {
count1++;
continue;
}
if (cand2 == num) {
count2++;
continue;
}
// 第1个候选人配对
if (count1 == 0) {
cand1 = num;
count1++;
continue;
}
// 第2个候选人配对
if (count2 == 0) {
cand2 = num;
count2++;
continue;
}
count1--;
count2--;
}
// 计数阶段
// 找到了两个候选人之后,需要确定票数是否满足大于 N/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;
}
}
标签:数组,nums,++,II,num,229,count1,count2,LeetCode 来源: https://blog.csdn.net/Galahadzhou/article/details/104640569