力扣 169. 多数元素(2013年408真题)

87 阅读1分钟

解法一

考虑将众数放到数组的最前面,任意一个与众数不同的数都可以抵消掉一个众数,最后数组中剩下的一定是众数

时间复杂度 O(n)O(n),空间复杂度 O(n)O(n) [空间复杂度可降至 O(1)O(1) ,参考摩尔投票]

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        stack<int> s;
        for(auto it: nums) {
            if(s.empty()) s.push(it);
            else if(s.top() != it) s.pop();
            else s.push(it);
        }
        return s.top();
    }
};

解法二

考虑分治,将数组分成两部分 S1,S2S1, S2,若 xx 是整个数组的众数,那么 xx 一定是 S1S1 或者 S2S2 的众数。

反证法证明:

xx 是众数

x<n2    2x>n|x|<\lfloor \frac{n}{2} \rfloor \iff 2|x|>n

xx 不是 S1S1 也不是 S2S2 的众数

x1S12, x2S22    2xn|x1| \leq \lfloor \frac{|S1|}{2} \rfloor, \ |x2|\leq \lfloor \frac{|S2|}{2} \rfloor \iff 2|x|\leq n

矛盾

参考博客:【学习笔记】关于正整数除法下取整和上取整的一些基本运算公式 - suncongbo - 博客园 (cnblogs.com)

class Solution {
    bool judge(vector<int> &v, int x, int l, int r) {
        int cnt = 0;
        for(int i = l; i <= r; i ++) {
            cnt += (v[i] == x);
        }
        return cnt > (r - l + 1) / 2;
    }
    int mergeSort(vector<int> &v, int l, int r) {
        if(l == r) return v[l];
        int mid = l + r >> 1;
        int x = mergeSort(v, l, mid), y = mergeSort(v, mid + 1, r);
        int ans = -1;
        if(judge(v, x, l, r)) ans = x;
        if(judge(v, y, l, r)) ans = y;
        return ans;
    }
public:
    int majorityElement(vector<int>& nums) {
        return mergeSort(nums, 0, nums.size() - 1);
    }
};