进阶:尝试设计时间复杂度为 O(n)、空间复杂度为 O(1)的算法解决此问题
题解:摩尔投票法选出出现频数最多的值。O(N)时间,O(1)空间。
摩尔投票法分为两个阶段:抵消阶段和计数阶段。
抵消阶段: 两个不同投票进行对坑,并且同时抵消掉各一张票,如果两个投票相同,则累加可抵消的次数;
计数阶段: 在抵消阶段最后得到的抵消计数只要不为 0,那这个候选人是有可能超过一半的票数的,为了验证,则需要遍历一次,统计票数,才可确定。
升级的摩尔投票在于最终的候选者(众数)有一个或者两个;因为题目要求了超过N/3,如果有三个候选人。那么不会有大于N/3的候选者。
class Solution {
public:
vector<int> majorityElement(vector<int>& nums) {
vector<int> res;
if (nums.size() == 0) return res;
// 初始化两个候选人candidate,和他们的计票
int cand1 = nums[0], count1 = 0;
int cand2 = nums[0], count2 = 0;
// 摩尔投票法,分为两个阶段:抵消阶段和计数阶段
// 抵消阶段
for (int i=0;i<nums.size();i++) {
// 投票
if (cand1 == nums[i]) {
count1++;
continue;
}
if (cand2 == nums[i]) {
count2++;
continue;
}
// 第1个候选人抵消
if (count1 == 0) {
cand1 =nums[i];
count1++;
continue;
}
// 第2个候选人抵消
if (count2 == 0) {
cand2 = nums[i];
count2++;
continue;
}
count1--;
count2--;
}
// 计数阶段
// 找到了两个候选人之后,需要确定票数是否满足大于 N/3
count1 = 0;
count2 = 0;
for (int i=0;i<nums.size();i++) {
if (cand1 == nums[i]) count1++;
else if (cand2 == nums[i]) count2++;
}
if (count1 > nums.size() / 3) res.push_back(cand1);
if (count2 > nums.size() / 3) res.push_back(cand2);
return res;
}
};