05 August 2008
Given an integer array of size n, find all elements that appear more than
times.1
⌊ n/3 ⌋
Note: The algorithm should run in linear time and in O(1) space.
Example 1:
1
2
Input: [3,2,3]
Output: [3]
Example 2:
1
2
Input: [1,1,1,3,3,2,2,2]
Output: [1,2]
跟169 Major Element相比,这道题是要求返回所出现次数超过1/3的元素,另外还规定了线性时间复杂度和常数时间,所以想利用数据结构来统计不可行;因为是出现次数大于1/3,所以众数最多是两个,最少是没有。做法是两次遍历,第一次遍历找出两个众数作为备选,第二次遍历利用投票方法确认这两个众数是否合格。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class Solution {
public List<Integer> majorityElement(int[] nums) {
List<Integer> result = new ArrayList<>();
if (nums == null || nums.length == 0) return result;
int candidate1 = 0, candidate2 = 0, count1 = 0, count2 = 0;
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--;
}
}
//重新计算一下两个备选众数的实际出现次数,看是否超过1/3
count1 = 0;
count2 = 0;
for (int num : nums) {
if (candidate1 == num) {
count1++;
} else if (candidate2 == num) { //else if 表示candidate1和candidate2不会是一个数
count2++;
}
}
if (count1 > nums.length/3) result.add(candidate1);
if (count2 > nums.length/3) result.add(candidate2);
return result;
}
}