Question
Given an integer array of size n, find all elements that appear more than ⌊ n/3 ⌋ times. The algorithm should run in linear time and in O(1) space.
hint
- How many majority elements could it possibly have?
- Do you have a better hint?
THOUGHT
Moore’s Majority Vote
algorithm,The basic idea is based on Moore’s Voting Algorithm, we need two candidates with top 2 frequency. If meeting different number from the candidate, then decrease 1 from its count, or increase 1 on the opposite condition. Once count equals 0, then switch the candidate to the current number. The trick is that we need to count again for the two candidates after the first loop. Finally, output the numbers appearing more than n/3 times.
多数投票算法进行改进的。观察可知,数组中至多可能会有2个出现次数超过 ⌊ n/3 ⌋ 的众数记变量n1, n2为候选众数; c1, c2为它们对应的出现次数,遍历数组,记当前数字为num。
若num与n1或n2相同,则将其对应的出现次数加1;
否则,若c1或c2为0,则将其置为1,对应的候选众数置为num;
否则,将c1与c2分别减1;
最后,再统计一次候选众数在数组中出现的次数,若满足要求,则返回之。
CODE
public class Solution {
public List<Integer> majorityElement(int[] nums) {
List<Integer> res = new ArrayList<Integer>();
if(nums == null || nums.length == 0)
return res;
if(nums.length == 1){
res.add(nums[0]);
return res;
}
int majNum1 = nums[0],majNum2 = nums[0],count1 = 1,count2 = 0;
for(int i = 0;i < nums.length;i++){
if(nums[i] == majNum1)
count1++;
else if(nums[i] == majNum2)
count2++;
else if(count1 == 0){
majNum1 = nums[i];
count1 = 1;
}
else if(count2 == 0){
majNum2 = nums[i];
count2 = 1;
}
else{
count1--;
count2--;
}
}
count1 = 0;
count2 = 0;
for(int i = 0;i < nums.length;i++){
if(nums[i] == majNum1)
count1++;
else if(nums[i] == majNum2)
count2++;
}
if(count1 > (nums.length/3))
res.add(majNum1);
if(count2 > (nums.length/3))
res.add(majNum2);
return res;
}
}
RESULT
run time complexity is O(n),space complexity is O(1);
二刷
只记得大概思路,多数投票算法如果是在给两人中的一人投票时,另一人的票数不会减少,只会在没给两人投票的情况下减少。还有一点就是,不要忘了最后还要统计下两人的票数有没有超过1/3;