题目描述:
Given an integer array of size n, find all elements that appear more than ⌊ n/3 ⌋ times.
Follow-up: Could you solve the problem in linear time and in O(1) space?
Example 1:
Input: nums = [3,2,3]
Output: [3]
Example 2:
Input: nums = [1]
Output: [1]
Example 3:
Input: nums = [1,2]
Output: [1,2]
Constraints:
1 <= nums.length <= 5 * 104
-109 <= nums[i] <= 109
Time complexity: O(n)
Space complexity: O(1)
摩尔投票法Boyer-Moore Voting Algorithm:
一般情况一个大小为 n 的整数数组,找出其中所有出现超过 ⌊ n/k ⌋ 次的元素。
则n/k的众数最多只有k - 1个。假设有k个众数,则 出现次数(⌊ n/k ⌋ +1) × \times × 众数个数 k > n. 以此题为例 k = 3, 把此情景想像成在大会中投票选出两个候选者, 则有两个候选 n1 和n2。
- 如果投n1(当前元素等于n1),则n1的票数 c1++;
- 如果投n2(当前元素等于n2),则n2的票数c2++;
- 如果n1,n2都不投(即当前值与n1,n2都不相等),那么检查此时n1或n2的票数是否为0:
3.1 如果为0,则当前元素成为新的候选人替代掉票数为0的人;
3.2 如果n1,n2两个人的票数都不为0,那么n1,n2两个候选人的票数均减一;
最后会有这么几种可能:有2个大于n/3,有1个大于n/3,有0个大于n/3,遍历结束后选出了两个候选人,但是这两个候选人是否满足> n/3,还需要再遍历一遍数组,找出两个候选人的具体票数,因为题目没有像169题保证一定有。
相似题:leetcode:169
class Solution {
public List<Integer> majorityElement(int[] nums) {
List<Integer> res = new ArrayList<>();
int c1 = 0;
Integer n1 = nums[0];
int c2 = 0;
Integer n2 = nums[0];
for (int n: nums) {
if(n1 != null && n1 == n){
c1++;
}else if(n2 != null && n2 == n){
c2++;
}else if(c1 == 0){
c1++;
n1 = n;
}else if(c2 == 0){
c2++;
n2 = n;
}else{
c1--;
c2--;
}
}
c1 = 0;
c2 = 0;
for (int n: nums) {
if(n == n1){
c1++;
}else if(n == n2){
c2++;
}
}
int n = nums.length;
if(c1 > n/3){
res.add(n1);
}
if(c2 > n/3){
res.add(n2);
}
return res;
}
}