Skip to content

题目链接 · 灵神原题解(署名来源)

题意:计算 nums绝对众数。绝对众数的出现次数,比其余所有元素的出现次数加起来还多。题目保证 nums 一定存在绝对众数。

尝试设计一个 O(n) 一次遍历,同时只用到 O(1) 额外空间的算法。

想象一众武林高手比武,谁会笑到最后?

我用「擂台赛」打比方:

  1. 擂主登场nums[0] 成为初始擂主,生命值为 1
  2. 挑战者出现:遍历后续元素,作为挑战者。
  3. 比武:如果挑战者与擂主属于同一门派(值相同),那么擂主生命值加 1,否则擂主生命值减 1
  4. 擂主更迭:如果比武后,擂主生命值降为 0(同归于尽),那么下一个挑战者成为新的擂主,生命值为 1
  5. 最后在擂台上的那人,便是武林盟主(绝对众数)。

为什么这样做是对的?

设出现次数最多的元素的出现次数为 a,其余元素的出现次数之和为 b=na。题目保证 a>b

证明:上述过程中,每次擂主的生命值降为 0 时,相当于开了一个新的擂台赛,在 nums[i1]nums[i] 之间切一刀。这会把 nums 分成若干段。依次考察这些段:

  • 对于除了最后一段的每一段(注意这些段的擂主不一定是绝对众数,比如绝对众数是 9,这一段是 [1,1,2,9]),设绝对众数在其中出现了 x 次,其余元素的出现次数之和为 y,则必然有 xy。这可以用反证法证明,如果 x>y,那么绝对众数血多,不可能被其余元素同归于尽,绝对众数的生命值在这段结束时必然大于 0,矛盾。由此可得 ax>by,意思是,把 a 减去 xb 减去 y,所得到的 ab 仍然满足 a>b。依此类推,每一段结束时,在剩余元素(未遍历到的元素)中,设出现次数最多的元素的出现次数为 a,其余元素的出现次数之和为 b,那么 a>b 始终成立。
  • 对于最后一段,由于 a>b,绝对众数血多,不可能被其余元素同归于尽,绝对众数的生命值最终必然大于 0,所以最后在擂台上的是绝对众数。
python
class Solution:
    def majorityElement(self, nums: List[int]) -> int:
        ans = hp = 0
        for x in nums:
            if hp == 0:  # x 是初始擂主,生命值为 1
                ans, hp = x, 1
            else:  # 比武,同门加血,否则扣血
                hp += 1 if x == ans else -1
        return ans
cpp
// C++ 版待补充
cpp
class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int ans = 0, hp = 0;
        for (int x : nums) {
            if (hp == 0) { // x 是初始擂主,生命值为 1
                ans = x;
                hp = 1;
            } else { // 比武,同门加血,否则扣血
                hp += x == ans ? 1 : -1;
            }
        }
        return ans;
    }
};

复杂度分析

  • 时间复杂度:O(n),其中 nnums 的长度。
  • 空间复杂度:O(1)

思考题

给定数组 nums,判断 nums 是否存在绝对众数。

欢迎在评论区分享你的思路/代码。

分类题单

如何科学刷题?

  1. 滑动窗口与双指针(定长/不定长/单序列/双序列/三指针/分组循环)
  2. 二分算法(二分答案/最小化最大值/最大化最小值/第K小)
  3. 单调栈(基础/矩形面积/贡献法/最小字典序)
  4. 网格图(DFS/BFS/综合应用)
  5. 位运算(基础/性质/拆位/试填/恒等式/思维)
  6. 图论算法(DFS/BFS/拓扑排序/基环树/最短路/最小生成树/网络流)
  7. 动态规划(入门/背包/划分/状态机/区间/状压/数位/数据结构优化/树形/博弈/概率期望)
  8. 常用数据结构(前缀和/差分/栈/队列/堆/字典树/并查集/树状数组/线段树)
  9. 数学算法(数论/组合/概率期望/博弈/计算几何/随机算法)
  10. 贪心与思维(基本贪心策略/反悔/区间/字典序/数学/思维/脑筋急转弯/构造)
  11. 链表、树与回溯(前后指针/快慢指针/DFS/BFS/直径/LCA)
  12. 字符串(KMP/Z函数/Manacher/字符串哈希/AC自动机/后缀数组/子序列自动机)

我的题解精选(已分类)

欢迎关注 B站@灵茶山艾府

本文整理自灵茶山艾府(endlesscheng)的公开内容,仅供个人学习使用

本站仅供个人学习使用,请勿外传