229. Majority Element II

时间:2022-01-21 00:41:55

#题目
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 ⌋ ,这个限制条件就限制了频繁项的个数一定小于等于2。又因为题目要求使用O(1)的空间和O(n)的时间,因此我们可以借鉴多数投票表决算法。Hesselink在2005年发表了一篇文章,文章中提出了一种The Boyer-Moore Majority Vote Algorithm with a majority of voting rabbits的方法。

  • 我们先来看下算法要解决的问题是:
    假设你有一个没有排序的整数数组。 你想知道列表中是否存在列表中超过一半的值。 如果存在,这样的值是什么? 如果不存在,你需要确定不存在。 你需要足够高效地完成解决这个问题。
    该问题一般性的思路就是,先将数组排序,如果存在绝大多数项,那么中间数必定是绝大多数项,最后只需要扫描一遍数组,确定是否重复次数超过数组大小的一半。

最后Hesselink提出的多数投票表决法,完美的解决了上述问题,时间复杂度为O(n),空间复杂度为O(1)。该算法只需要扫描数组两遍:

  • 第一遍:如果存在绝大多数项,找到绝大多数项
  • 第二遍:统计第一遍找到的数值出现的次数,是否满足题目要求

如果整数列表中存在超过一半的值,这个值有且只有一个
很明显算法的核心部分在第一遍遍历寻找重复项的过程中:

在第一遍遍历中,我们需要2个值:
candidate1,最初可以设置为任何值。
count1,最初设置为0。

对于我们输入数组中的每个元素,我们首先检查count1。 如果count1等于0,我们将候选值设置为当前元素的值。 接下来,首先比较元素的值和当前的candidate1。 如果他们是一样的,我们count1加1.如果他们不同,我们count1减1。

最后我们再遍历数组求candidate1的出现次数,来验证是否满足题目要求。

而在本题中,因为如果出现满足题目要求的数,那么这个数的个数一定小于等于2;因此我们维护两个值:
candidate1,candidate2,最初可以设置为任何值。
count1,count2,最初设置为0。

note:如果看不明白,可以结合代码与测试例子来加深理解
#代码

class Solution {
public:
    vector<int> majorityElement(vector<int>& nums) {
        vector<int> res;
        if(nums.size()<0)
            return res;
        int candidate1=0,candidate2=0,count1=0,count2=0;
        for(auto item:nums)
        {
            if(item==candidate1)
                count1++;
            else if(item==candidate2)
                count2++;
            else if(count1==0)
            {
                candidate1=item;
                count1=1;
            }  
            else if(count2==0)
            {
                candidate2 = item;
                count2=1;
            }  
            else
            {
                count1--;
                count2--;
            }
        }
        count1=0;
        count2=0;
        for(auto item:nums)
        {
            if(candidate1==item)
                count1++;
            if(candidate2==item)
                count2++;
        }
        
        if(candidate1!=candidate2)
        {
            if(count1>nums.size()/3)
                res.push_back(candidate1);
            if(count2>nums.size()/3)
                res.push_back(candidate2);
            return res;
        }
        else
        {
            if(count1>nums.size()/3)
                res.push_back(candidate1);
            return res;
        }
        
    }
};