题目描述:
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.
暴力法超时,哈希表法空间复杂度超过。
摩尔投票法
假设an={2,2,3,3,1,4,0}
第一轮:每次存储两个元素n1和n2,如果第三个元素与其中一个相同,则增加计数cn1或cn2, 否则,清除cn1-1,cn2-1.
第二轮:验证这两个元素是否满足条件,即出现的次数是否大于n/3.
注意:在这里数组中存储的并不是数组中较多的两个数,例如an最后numbers中存储的是0,3。显然0只有1个,2有2个。但是此时因为2的个数已经小于an.length/3,它不可能符合题意,所以被替换成0也没关系。
代码如下:
public List<Integer> majorityElement(int[] nums) {
List<Integer> result = new ArrayList<Integer>();
//注意null和nums.length==0
if(nums == null || nums.length == 0){
return result;
}
int[] numbers = new int[2];
int[] count = new int[2];
for(int i = 0 ; i < nums.length ; i++){
//&&条件不能掉
if(count[0] == 0 && numbers[1] != nums[i]){
numbers[0] = nums[i];
}else if(count[1] == 0 && numbers[0] != nums[i]){
numbers[1] = nums[i];
}
//只有3种情况
if(numbers[0] == nums[i]){
count[0]++;
}else if(numbers[1] == nums[i]){
count[1]++;
}else{
count[0]--;
count[1]--;
}
}
count[0] = count[1] = 0;
for(int i = 0 ; i < nums.length ; i++){
for(int j = 0 ; j < numbers.length ; j++){
if(nums[i] == numbers[j]){
count[j]++;
}
}
}
if(count[0] > nums.length / 3)
result.add(numbers[0]);
//这个条件一定要注意,否则当全是0的时候result里面就有2个0了,因为numbers数组初始值为0
if(count[1] > nums.length / 3&&numbers[1]!=numbers[0])
result.add(numbers[1]);
return result;
}