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? Suggest it!
这道题是找出数组中数量超过1/3的元素,题目难度为Medium。
题目和169题(传送门)相关,大家可以先看下169题。由于限定了时间和空间复杂度,所以排序和Hash Table不能用了,只想到用多数投票算法,有其他方法的同学可以留言。
多数投票算法的核心思想是依次去除成对的不同元素,最后剩下的元素就有可能是所求的majority element,如果majority element存在,则最后剩下的元素中必定有它,这样再遍历数组统计最后剩下元素的个数即可判断是否是majority element。第169题找过半的元素,所以每次去除两个不同的元素(在num != major && count != 0时将count--,这样就相当于去除了两个不同的元素),如果存在majority element,最后剩下的元素就是它,题目设定存在majority element,所以用多数投票选出的元素就是majority element,因此没有重新遍历数组统计它的个数。
这里找个数超过1/3的元素,最多有两个,可以用反证法证明,就不详细证明了。每次去除三个不同的元素,如果存在majority element,必定在最后剩下的元素中,之后再统计剩下元素出现的次数即可判断是否是majority element了。具体代码:
class Solution {
public:
vector<int> majorityElement(vector<int>& nums) {
vector<int> ret;
int major1, major2;
int count1 = 0, count2 = 0;
for(int num:nums) {
if(num == major1) count1++;
else if(num == major2) count2++;
else if(count1 == 0) {
major1 = num;
count1++;
}
else if(count2 == 0) {
major2 = num;
count2++;
}
else {
count1--;
count2--;
}
}
count1 = count2 = 0;
for(int num:nums) {
if(num == major1) count1++;
else if(num == major2) count2++;
}
if(count1 > nums.size()/3) ret.push_back(major1);
if(count2 > nums.size()/3) ret.push_back(major2);
return ret;
}
};