[leetcode] 229. Majority Element II 解题报告

题目链接:https://leetcode.com/problems/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.

Hint:

  1. How many majority elements could it possibly have?
  2. Do you have a better hint? Suggest it!

思路:这道题目有两种解法,第一种是基本快速排序。在快速排序中有个partition函数可以将数组两部分,左边是比这个数小的数,右边是比这个值大的数。

在这题中我们要找到出现次数超过1/3的数,那么这个数最多有两个,利用partition找出应该出现在数组1/3处,和2/3处的值,则出现超过1/3的数必然在这两个数中。然后再验证这两个数是不是解。这种解法的时间复杂度是O(n),因为要找两个数,比较麻烦。

还有另外一种解法是BM投票算法(Boyer-Moore Majority Vote algorithm),这种算法是设置一个数的计数器,在遍历数组的时候,如果是这个数,则计算器加一,不是则减一,用来计数超过一半的数非常方便。在这里我们需要进行改进一下,设置两个计数器,来统计两个数出现的次数。

如果是这两个数中的一个,则他的计算器加1,如果不是这两个数中的任何一个,则计算器都减1,如果计数器为0了,则统计当前的这个数。那么如果一个数出现次数超过1/3,则最后必然出现在统计的数中,但是我们不能确定现在得到的这两个数出现次数是否超过1/3,因此最后需要再验证一下。

边界条件:如果数组长度为1,则需要判断最后得到的两个数是否一样。

代码如下:

class Solution {
public:
    vector<int> majorityElement(vector<int>& nums) {
        int cnt1 = 0, cnt2 = 0, num1, num2, len = nums.size();
        if(len == 0) return result;
        
        for(int i = 0; i < len; i++)
        {
            if(cnt1 == 0) 
                num1 = nums[i];
            if(cnt2 == 0) 
                num2 = nums[i];
            if(nums[i] == num1) 
                cnt1++;
            else if(nums[i] == num2) 
                cnt2++;
            else
            {
                cnt1--;
                cnt2--;
            }
        }
        cnt1 = cnt2 = 0;
        for(int i =0; i< len; i++)//验证是否出现次数超过1/3
        {
            cnt1 = (nums[i]==num1)?(cnt1+1):cnt1;
            cnt2 = (nums[i]==num2)?(cnt2+1):cnt2;
        }
        if(cnt1 > len/3.0f) 
            result.push_back(num1);
        if(num1 != num2 && cnt2 > len/3.0f) 
            result.push_back(num2);
        return result;
    }
private:
    vector<int> result;
};
参考:http://www.neozone.me/leetcode229.html

你可能感兴趣的:(LeetCode,array)