# 229.求众数II
给定一个大小为 n 的整数数组,找出其中所有出现超过 ⌊ n/3 ⌋
次的元素。
进阶:尝试设计时间复杂度为 O(n)
、空间复杂度为 O(1)
的算法解决此问题。
输入:[3,2,3]
输出:[3]
输入:[1,1,1,3,3,2,2,2]
输出:[1,2]
输入:nums = [1]
输出:[1]
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 思路
哈希表记录出现的次数,这种空间复杂度不为
O(1)
利用投票算法
投票算法的原理是通过不断消除不同元素直到没有不同元素,剩下的元素就是我们要找的元素。
TIP
抵消阶段:两个不同投票进行对坑,并且同时抵消掉各一张票,如果两个投票相同,则累加可抵消的次数;
计数阶段:在抵消阶段最后得到的抵消计数只要不为 0
,那这个候选人是有可能超过一半的票数的,为了验证,则需要遍历一次,统计票数,才可确定。
摩尔投票法经历两个阶段最多消耗 O(2n)
的时间,也属于 O(n)
的线性时间复杂度,另外空间复杂度也达到常量级。
- 如果至多选一个代表,那他的票数至少要超过一半
(⌊ 1/2 ⌋)
的票数; - 如果至多选两个代表,那他们的票数至少要超过
⌊ 1/3 ⌋
的票数; - 如果至多选m个代表,那他们的票数至少要超过
⌊ 1/(m+1) ⌋
的票数。
# 解答
- 投票算法的模板
/**
* @param {number[]} nums
* @return {number[]}
*/
var majorityElement = function(nums) {
const len=nums.length
if(len===0||len===1) return nums
let count1=0,count2=0 //初始票数
let candicate1=nums[0],candicate2=nums[1] //初始化候选人
let ans=[]
//摩尔投票过程
for(let num of nums){
if(num===candicate1){ //候选人1投票
count1++
continue
}
if(num===candicate2){ //候选人2投票
count2++
continue
}
if(count1===0){ //当候选人1票数为0时,无法再与其他候选人对抗,于是更换候选人
candicate1=num
count1++
continue
}
if(count2===0){ //当候选人2票数为0时,无法再与其他候选人对抗,于是更换候选人
candicate2=num
count2++
continue
}
//其他候选人与候选人1,2对抗
count1--
count2--
}
//重置候选人1,2的票数为0,为之后检票做准备
count1=0
count2=0
//检票过程,判断候选人1,2的票数是否超过len/3
for(let num of nums){
if(num===candicate1) count1++
if(num===candicate2) count2++
}
if(count1>Math.floor(len/3)) ans.push(candicate1)
if(count2>Math.floor(len/3)) ans.push(candicate2)
return [...new Set(ans)]
};
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
39
40
41
42
43
44
45
46
47
48
49
50
51
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
39
40
41
42
43
44
45
46
47
48
49
50
51
# 169. 多数元素
给定一个大小为 n
的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋
的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
var majorityElement = function(nums) {
let count = 1
let result = nums[0]
for(let i=1;i<nums.length;i++) {
if(count === 0) {
result = nums[i] // 更换候选人
}
if(nums[i] === result) {
count++
} else {
count--
}
}
return result
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15