LeetCode #229. Majority Element II 数组 摩尔投票法

Description


Given an integer array of size n, find all elements that appear more than ⌊ n/3 ⌋ times.

Note: The algorithm should run in linear time and in O(1) space.

Example 1:

Input: [3,2,3]
Output: [3]

Example 2:

Input: [1,1,1,3,3,2,2,2]
Output: [1,2]



思路


解法一

借鉴了#169 中的摩尔投票法,但是使用该算法的前提是数组必须存在一个 majorityElement 且它的出现频数大于数组元素数目的一半。因此,需要对该算法进行修改。

由题推得,任意一个数组出现次数大于 n/3 的数最多有两个,网上提供了证明:如果有超过两个,也就是至少三个数字满足“出现的次数大于 n/3”,那么就意味着数组里总共有超过 3*(n/3) = n 个数字,这与已知的数组大小矛盾,所以,只可能有两个或者更少。

原来的算法只是利用一个计数器,现在新增一个计数器,用两个计数器来统计出现次数大于 n/3 的数。

如果当前数字是这两个数中的一个,则对应计数器 + 1;
如果当时数字不是这两个数中的一个,则两个计数器都减一;
如果有一个计数器的值为 0 ,则该计数器重置为 1,用来统计当前数字的出现次数。

这三个判断必须以 if-else 方式执行,否则将不符合 Moore Voting 的思想。

由于之前 #169 中限定了一定会有大多数存在,故而当时省略了验证候选众数的步骤。但是这道题却没有这种限定,即满足要求的Majority Element可能不存在,所以要有验证步骤。

时间复杂度:O(n)
空间复杂度:O(1)

耗时 12 ms, Memory 8.5 MB, ranking 89.57%

class Solution {
public:
    vector<int> majorityElement(const vector<int> &nums) {
        if (nums.empty()) return {};
        
        int mj1 = 0, mj2 = 0, cnt1 = 0, cnt2 = 0;
        for (int element : nums) {
            if (element == mj1) {
                ++cnt1;
            } else if (element == mj2) {
                ++cnt2;
            } else if (!cnt1) {
                mj1 = element;
                cnt1 = 1;
            } else if (!cnt2) {
                mj2 = element;
                cnt2 = 1;
            } else {
                --cnt1;
                --cnt2;
            }
        }
        
        // recheck whether both mj1 and mj2 are majority element
        cnt1 = 0, cnt2 = 0;
        for (int element : nums) {
            if (element == mj1) {
                ++cnt1;
                continue;  // mj1 != mj2, so don't need to judge next condition
            }
            
            if (element == mj2) {
                ++cnt2;
                continue;
            }
        }
        
        int len = nums.size()/3;  // 2 = 8 / 3
        if (cnt1 > len && cnt2 > len) {
            return {mj1, mj2};
        } else if (cnt1 > len) {
            return {mj1};
        } else if (cnt2 > len) {
            return {mj2};
        } else {
            return {};
        }
    }
};



参考




原文地址:https://www.cnblogs.com/Bw98blogs/p/12712057.html