今天了遇到了Leecode229——众数||题:给定一个大小为 n 的整数数组,找出其中所有出现超过 ⌊ n/3 ⌋ 次的元素。常规法用哈希表即可得出,另外还有一种线性算法即可实现——摩尔投票法。
摩尔投票法
1、原因:对于任意一个大小为n的数组,出现次数超过n/2的元素个数不超过1。
2、算法过程:假定k就是所要找的元素,用c记录当前遍历得到k的次数,遍历一次数组,每当遇到与k不同的数字,就将c-1,即将k与一个不同的数抵消。当c==0时,就将当前遍历得到的数字记作k,c调为1。
3、解释:如果数组中存在k这样的数,在遍历一次数组后,出现次数超过n/2的元素一定是k,不过,若数组中没有n/2的数,也会遍历出一个k,因此最后需要再次遍历数组检查k是否满足条件。
题解:
因为数组中最多只有2两个数出现次数超过n/3,因此定义k1和k2来记录元素,c1和c2记录出现次数,遍历两次数组即可。
public List<Integer> majorityElement(int[] nums){
int k1=0,k2=0,c1=0,c2=0;
for(int i=0;i<nums.length;++i){
if(nums[i]==k1&&c1>0){
c1++;
}else if(nums[i]==k2&&c2>0){
c2++;
}else if(c1==0){
k1=nums[i];
c1++;
}else if(c2==0){
k2=nums[i];
c2++;
}else{
c1--;
c2--;
}
}
c1=0;
c2=0;
for(int i=0;i<nums.length;++i){
if(nums[i]==k1) c1++;
if(nums[i]==k2) c2++;
}
List<Integer> list=new LinkedList<>();
if(c1>nums.length/3) list.add(k1);
if(c2>nums.length/3&&k1!=k2) list.add(k2);
return list;
}