[LeetCode 229] Majority Element II

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]

 

This is an extension of the Boyer-Moore Voting Majority Algorithm covered in the Majority Element problem. The difference is that there may be up to 2 different numbers whose frequencies are > n / 3. Instead of running 1 candidate and 1 counter, we run 2 candidates and 2 counters for each.  Assign two different numbers to candidate 1 and 2, the actual values here do not matter as long as they are not the same. Then go over the input array and do the following.

 

1. if nums[i] == candidate1, cnt1++;

2. else if nums[i] == candidate2, cnt2++;

3. else if cnt1 == 0, set candidate1 to nums[i];

4. else if cnt2 == 0, set candidate2 to nums[i];

5. else cnt1--, cnt2--. 

 

Why do we need to decrease both counters in case 5? Think of it this way: we are trying to find 3 different numbers to hide. In case 5, we have just found an all different triplet. We hide all 3 different numbers: nums[i] is ignored, candidate1 and candidate2' counters decrease by 1. 

 

Why does this modification on the voting algorithm works? If there is at least 1 numbers with > n / 3 frequency, then in order to completely hide it, we need > n / 3 * 2 numbers of different value to achieve this. This exceeds the total number of elements n. 

 

class Solution {
    public List<Integer> majorityElement(int[] nums) {
        List<Integer> ans = new ArrayList<>();
        int c1 = 0, c2 = 1, cnt1 = 0, cnt2 = 0;
        for(int i = 0; i < nums.length; i++) {
            if(nums[i] == c1) {
                cnt1++;
            }
            else if(nums[i] == c2) {
                cnt2++;
            }
            else if(cnt1 == 0) {
                c1 = nums[i];
                cnt1++;
            }
            else if(cnt2 == 0) {
                c2 = nums[i];
                cnt2++;
            }
            else {
                cnt1--;
                cnt2--;
            }
        }
        cnt1 = 0;
        cnt2 = 0;
        for(int i = 0; i < nums.length; i++) {
            if(nums[i] == c1) {
                cnt1++;
            }
            else if(nums[i] == c2) {
                cnt2++;
            }
        }
        if(cnt1 > nums.length / 3) {
            ans.add(c1);
        }
        if(cnt2 > nums.length / 3) {
            ans.add(c2);
        }
        return ans;
    }
}

 

 

Related Problems 

Majority Element 

Majority Element III

Single Number 

Single Number II

Single Number III

posted @ 2020-05-22 06:10  Review->Improve  阅读(158)  评论(0编辑  收藏  举报