【摩尔投票】LeetCode 229. 多数元素 II
题目
https://leetcode.cn/problems/majority-element-ii/description/
题解
在一个长为 \(n\) 的数组中,如果有一个数的出现次数会超过 \(\frac{n}{2}\) 次,用多阵营厮杀的观念来看待,超过 \(\frac{n}{2}\) 次的为胜方阵营,其他阵营就统一视为败方阵营,规则为一个胜方阵营的士兵可以与败方阵营的一个士兵同归于尽,由于胜方阵营的人数大于 \(\frac{n}{2}\),因此最后肯定还有剩余士兵存活。
推广到在一个长为 \(n\) 的数组中,如果有两个数的出现次数会超过 \(\frac{n}{3}\) 次,就可以用维护两个变量,视为两个阵营,然后再用两个变量维护这两个变量的剩余存活人数。若新枚举的士兵,可以成立一个新的阵营(也就是存在无人存活的阵营),就用变量维护它;否则判断是否属于已存在的阵营,若是则增加人数,否则两个阵营都需要牺牲一个士兵。最后剩余的,便是出现次数超过 \(\frac{n}{3}\) 的。
时间复杂度:\(O(n)\)
空间复杂度:\(O(1)\)
参考代码
class Solution {
private:
const int INF = 0x3f3f3f3f;
public:
vector<int> majorityElement(vector<int>& nums) {
vector<int> ans;
int x = INF, y = INF, cnt_x = 0, cnt_y = 0, sz = nums.size();
for (auto &it: nums) {
if (it != y && (!cnt_x || it == x)) {
x = it;
++ cnt_x;
} else if (it == y || !cnt_y) {
y = it;
++ cnt_y;
} else {
-- cnt_x;
-- cnt_y;
}
}
cnt_x = cnt_y = 0;
for (auto &it: nums) {
if (it == x) ++ cnt_x;
else if (it == y) ++ cnt_y;
}
if (cnt_x > sz / 3) {
ans.emplace_back(x);
}
if (cnt_y > sz / 3) {
ans.emplace_back(y);
}
return ans;
}
};
浙公网安备 33010602011771号