Leetcode之Majority Element I II

169. Majority Element 求众数

Given an array of size n, find the majority element. The majority element is the element that appears more than ⌊ n/2 ⌋ times.
You may assume that the array is non-empty and the majority element always exist in the array.

方法一:Boyer-Moore Voting摩尔投票法
Boyer-Moore Voting法先将第一个数字假设为众数,然后把计数器设为1,比较下一个数和此数是否相等,若相等则计数器加一,反之减一。然后看此时计数器的值,若为零,则将当前值设为候选众数。以此类推直到遍历完整个数组,当前候选众数即为该数组的众数。由于题目中限定了一定会有众数存在,故而省略了验证候选众数的步骤。
该方法的时间复杂度为O(n),空间复杂度为O(1)。

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int count = 1;
        int majority = nums[0];
        for(int i = 1;i < nums.size();i++){
            if(nums[i] == majority)
                count++;
            else
                count--;
            if(count == 0){
                majority = nums[i];
                count = 1;
            }
        }
    }
};

方法二:哈希表
使用哈希表,键用来存放数组的元素,键对应的值存放元素出现的次数。遍历整个数组,查找它在hash表中是否出现,如果出现将出现次数加1,如果没有出现,将它插入哈希表中,并设置它的出现次数为1。每次遍历到一个元素,判断它的出现次数是否超过了数组长度的一半,要是超过了就返回该元素。
时间复杂度是O(n),空间复杂度是O(n)。

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        if(nums.size()==1)
            return nums[0];
        unordered_map<int,int> mp;
        for(int i=0;i<nums.size();i++){
            if(mp.count(nums[i])){
                mp[nums[i]]++;
                if(mp[nums[i]]>nums.size()/2)
                    return nums[i];
            }
            else
                mp[nums[i]]=1;
        }
};

方法三:排序
对数组进行排序,那么出现次数超过一半的元素必定是数组中的中间元素,返回这个元素即可。
时间复杂度是O(nlogn),空间复杂度是O(1)。

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        return nums[nums.size()/2];
    }
};

方法四:位操作Bit Manipulation
将中位数按位来建立,从0到31位,每次统计下数组中该位上0和1的个数,如果1多,那么我们将结果res中该位变为1,最后累加出来的res就是中位数了

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int res = 0;
        for (int i = 0; i < 32; ++i) {
            int ones = 0, zeros = 0;
            for (int num : nums) {
                if ((num & (1 << i)) != 0) ++ones;
                else ++zeros;
            }
            if (ones > zeros) res |= (1 << i);
        }
        return res;
    }
};

229. Majority Element II

Given an integer array of size n, find all elements that appear more than ⌊ n/3 ⌋ times. The algorithm should run in linear time and in O(1) space.

这道题让我们求出现次数大于n/3的众数,而且限定了时间和空间复杂度,那么就不能排序,也不能使用哈希表,这么苛刻的限制条件只有一种方法能解了,那就是摩尔投票法 Moore Voting,这种方法在之前那道题Majority Element 求众数中也使用了。有一个重要的结论,任意一个数组出现次数大于n/3的众数最多有两个。我们使用投票法的核心是找出两个候选众数进行投票,需要两遍遍历,第一遍历找出两个候选众数,第二遍遍历重新投票验证这两个候选众数是否为众数即可,选候选众数方法和前面Majority Element 求众数一样,由于之前那题题目中限定了一定会有众数存在,故而省略了验证候选众数的步骤,这道题却没有这种限定,即满足要求的众数可能不存在,所以要有验证。

class Solution {
public:
    vector<int> majorityElement(vector<int>& nums) {
        vector<int> res;
        int m = 0, n = 0, cm = 0, cn = 0;
        for (auto &a : nums) {
            if (a == m) ++cm;
            else if (a == n) ++cn;
            else if (cm == 0) m = a, cm = 1;
            else if (cn == 0) n = a, cn = 1;
            else --cm, --cn;
        }
        cm = cn = 0;
        for (auto &a : nums) {
            if (a == m) ++cm;
            else if (a == n) ++cn;
        }
        if (cm > nums.size() / 3) res.push_back(m);
        if (cn > nums.size() / 3) res.push_back(n);
        return res;
    }
};

猜你喜欢

转载自blog.csdn.net/qq_21815981/article/details/80151193