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:
- How many majority elements could it possibly have?
- Do you have a better hint? Suggest it!
解题思路:
这题是 Majority Element 的follow-up,但是不同的是,上题要求的是出现次数大于floor(n/2)的数字,这一题是要求出所有大于floor(n/3)。问题是,这样的数字可能有几个?
上一题很显然的,只要求出有且仅有的一个数字,而这一题,我们只要定心想一下,这样的数字最多只可能有两个。
还是用Boyer-Moore Majority Vote Algorithm的方法,很容易想到count和candidate的记数,各用两个变量去记录。
大体思路类似,问题是,当当前数字和candidate1、candidate2都不相等的时候,怎么办?
这里我们首先去抵消掉出现次数较小的那个。为什么?因为如果是较大的,那么count2就永远是1了。
另外,如果count1和count2都不为0的时候,count1和count2都要减一。这个非常重要,也比较容易理解。
public class Solution { public List<Integer> majorityElement(int[] nums) { List<Integer> res = new ArrayList<Integer>(); if(nums.length == 0) { return res; } if(nums.length == 1) { res.add(nums[0]); return res; } int count1 = 0, count2 = 0; int candidate1 = nums[0], candidate2 = nums[1]; for(int num : nums) { if(num == candidate1) { count1++; } else if(num == candidate2) { count2++; } else { if(count1 < count2) {//总是首先操作数量较少的数字 if(count1 == 0) { candidate1 = num; count1 = 1; } else { count1--; count2--; } } else { if(count2 == 0) { candidate2 = num; count2 = 1; } else { count1--; count2--; } } } } count1 = 0; count2 = 0; for(int num : nums) { if(num == candidate1) { count1++; } else if(num == candidate2) { count2++; } } if(count1 > nums.length / 3) { res.add(candidate1); } if(count2 > nums.length / 3) { res.add(candidate2); } return res; } }
后来在discuss里发现人家的解法和我的差不多,但是可以完全不用管count1和count2的大小,只要count1和count2里有一个==0,就去更新它就可以了。
代码如下
public class Solution { public List<Integer> majorityElement(int[] nums) { List<Integer> res = new ArrayList<Integer>(); if(nums.length == 0) { return res; } if(nums.length == 1) { res.add(nums[0]); return res; } int count1 = 0, count2 = 0; int candidate1 = nums[0], candidate2 = nums[1]; for(int num : nums) { if(num == candidate1) { count1++; } else if(num == candidate2) { count2++; } else { if(count1 == 0) { candidate1 = num; count1 = 1; } else if(count2 == 0) { candidate2 = num; count2 = 1; } else { count1--; count2--; } } } count1 = 0; count2 = 0; for(int num : nums) { if(num == candidate1) { count1++; } else if(num == candidate2) { count2++; } } if(count1 > nums.length / 3) { res.add(candidate1); } if(count2 > nums.length / 3) { res.add(candidate2); } return res; } }
这道题是蛮好的一个follow-up,借鉴了上一题的基本思路,由需要对题目有更深层次的理解。