[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
Single Number
Single Number II
Single Number III