力扣每日一题 2021/10/22

  1. 1. 229.求众数 II
  2. 2. 解题思路
  3. 3. 解题代码

229.求众数 II

给定一个大小为 n 的整数数组,找出其中所有出现超过 ⌊ n/3 ⌋ 次的元素。

示例 1:

1
2
输入:[3,2,3]
输出:[3]

示例 2:

1
2
输入:nums = [1]
输出:[1]

示例3

1
2
输入:[1,1,1,3,3,2,2,2]
输出:[1,2]

提示:

  • 1 <= nums.length <= 5 * 104
  • -109 <= nums[i] <= 109

    进阶:尝试设计时间复杂度为 O(n)、空间复杂度为 O(1)的算法解决此问题。

原文链接

解题思路

解法一

将数组排序,分别计算每个数字的数量,将符合要求的记录并返回

解法二

【笔记】摩尔投票法。该算法用于1/2情况,它说:“在任何数组中,出现次数大于该数组长度一半的值只能有一个。”

那么,改进一下用于1/3。可以着么说:“在任何数组中,出现次数大于该数组长度1/3的值最多只有两个。”

于是,需要定义两个变量。空间复杂度为O(1)。(摘自LeetCode评论区)

解题代码

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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
//Solution1

class Solution {
public List<Integer> majorityElement(int[] nums) {
Arrays.sort(nums);
int count = 1;
List<Integer> result = new ArrayList<>();
if (nums.length == 1){
result.add(nums[0]);
return result;
}
if(nums.length == 2){
if(nums[0] == nums[1]){
result.add(nums[0]);
}else{
result.add(nums[0]);
result.add(nums[1]);
}
return result;
}
boolean flag = true;
for(int i = 1;i < nums.length;i++){
if(nums[i] == nums[i - 1]){
count++;
}else{
flag = true;
count = 1;
}
if(count > (nums.length / 3) && flag){
result.add(nums[i - 1]);
flag = false;
}

}
return result;
}
}

//Solution2
class Solution {
public List<Integer> majorityElement(int[] nums){
int x = 0;
int y = 0;
int cx = 0;
int cy = 0;
int count = 0;
List<Integer> res = new ArrayList<>();
for (int num : nums){
if ((cx == 0 || num == x) && num != y){
++cx;
x = num;
} else if (cy == 0 || num == y){
++cy;
y = num;
} else {
--cx;
--cy;
}
}
for (int num : nums){
if (x == num){
++count;
}
}
if (count > nums.length/3){
res.add(x);
}
count = 0;
for (int num : nums){
if (y == num){
++count;
}
}
if (count > nums.length/3 && x != y){
res.add(y);
}
return res;
}
}