摩尔投票法
一个题:给定N个数,求出现次数大于N/2的数字,要求时间复杂度为O(N),空间复杂度为O(1)。
如果不要求时间复杂度和空间复杂度,有多种解法吧:1. 排序:如果这个数字存在,那么排序后它一定在N/2这个位置上。可以先排序,再验证N/2这个位置上的数字满不满足条件。
- 用HashMap
但是有这些限制就不行了,可以使用摩尔投票法:在每一轮投票过程中,从数组中找到一对不同的元素,将其从数组中删除。这样不断删除直到无法进行删除。如果数组空了,那么不存在 这样的元素。如果还剩一种数字,那么这个数字可能是结果。
代码如下:
public int majorityElement(int[] nums) {
int majority = -1;
int count = 0;
for (int num : nums) {
if (count == 0) {
majority = num;
count++;
}
else {
if (majority == num)
count++;
else
count--;
}
}
if (count <= 0)
return -1;
for (int num : nums) {
if (num == majority)
count++;
}
if (count > nums.length / 2)
return majority;
return -1
}
这道题还可以有拓展:给定N个数,求出次数大于N/3的数字,要求时间复杂度为O(N),空间复杂度为O(1). 这道题和上一题是同样的思路,即摩尔投票法。这种元素的个数可能为0,1,2。同样是分两步:1. 找到两个候选元素
- 验证这两个元素是不是满足条件。 代码如下:
···
public List
times1 = 0; times2 = 0;
for(int i = 0; i < n; i++){
if(nums[i] == candidate1) times1++;
else if(nums[i] == candidate2) times2++;
}
List<Integer> res = new ArrayList<Integer>();
if(times1 > n/3) {
res.add(candidate1);
}
if(times2 > n/3) {
res.add(candidate2);
}
return res;
//0649
} ···