Skip to content

Commit b07b46b

Browse files
committed
229
1 parent f2b981e commit b07b46b

File tree

3 files changed

+119
-1
lines changed

3 files changed

+119
-1
lines changed

SUMMARY.md

+1
Original file line numberDiff line numberDiff line change
@@ -208,4 +208,5 @@
208208
* [226. Invert Binary Tree](leetcode-226-Invert-Binary-Tree.md)
209209
* [227. Basic Calculator II](leetcode-227-Basic-CalculatorII.md)
210210
* [228. Summary Ranges](leetcode-228-Summary-Ranges.md)
211+
* [229. Majority Element II](leetcode-229-Majority-ElementII.md)
211212
* [更多](more.md)

leetcode-201-300.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,6 @@
5454

5555
<a href="leetcode-227-Basic-CalculatorII.html">227. Basic Calculator II</a>
5656

57-
<a href="leetcode-228-Summary-Ranges.html">228. Summary Ranges</a>
57+
<a href="leetcode-228-Summary-Ranges.html">228. Summary Ranges</a>
58+
59+
<a href="leetcode-229-Majority-ElementII.html">229. Majority Element II</a>

leetcode-229-Majority-ElementII.md

+115
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# 题目描述(中等难度)
2+
3+
![](https://windliang.oss-cn-beijing.aliyuncs.com/229.jpg)
4+
5+
找出数组中数量超过 `n/3` 的数字,`n` 是数组的长度。
6+
7+
# 解法一
8+
9+
题目要求是 `O(1)` 的空间复杂度,我们先用 `map` 写一下,看看对题意的理解对不对。
10+
11+
`map` 的话 `key` 存数字,`value` 存数字出现的个数。如果数字出现的次数等于了 `n/3 + 1` 就把它加到结果中。
12+
13+
```java
14+
public List<Integer> majorityElement(int[] nums) {
15+
int n = nums.length;
16+
HashMap<Integer, Integer> map = new HashMap<>();
17+
List<Integer> res = new ArrayList<>();
18+
for (int i = 0; i < n; i++) {
19+
int count = map.getOrDefault(nums[i], 0);
20+
//之前的数量已经是 n/3, 当前数量就是 n/3 + 1 了
21+
if (count == n / 3) {
22+
res.add(nums[i]);
23+
}
24+
//可以提前结束
25+
if (count == 2 * n / 3 || res.size() == 2) {
26+
return res;
27+
}
28+
map.put(nums[i], count + 1);
29+
30+
}
31+
return res;
32+
}
33+
```
34+
35+
# 解法二
36+
37+
[169 题](https://leetcode.wang/leetcode-169-Majority-Element.html) 我们做过找出数组的中超过 `n/2` 数量的数字,其中介绍了摩尔投票法,这里的话可以改写一下,参考 [这里](https://leetcode.com/problems/majority-element-ii/discuss/63520/Boyer-Moore-Majority-Vote-algorithm-and-my-elaboration)
38+
39+
首先看一下 [169 题](https://leetcode.wang/leetcode-169-Majority-Element.html) 我们是怎么做的。
40+
41+
> 我们假设这样一个场景,在一个游戏中,分了若干个队伍,有一个队伍的人数超过了半数。所有人的战力都相同,不同队伍的两个人遇到就是同归于尽,同一个队伍的人遇到当然互不伤害。
42+
>
43+
> 这样经过充分时间的游戏后,最后的结果是确定的,一定是超过半数的那个队伍留在了最后。
44+
>
45+
> 而对于这道题,我们只需要利用上边的思想,把数组的每个数都看做队伍编号,然后模拟游戏过程即可。
46+
>
47+
> `group` 记录当前队伍的人数,`count` 记录当前队伍剩余的人数。如果当前队伍剩余人数为 `0`,记录下次遇到的人的所在队伍号。
48+
49+
对于这道题的话,超过 `n/3` 的队伍可能有两个,首先我们用 `group1``group2` 记录这两个队伍,`count1``count2` 分别记录两个队伍的数量,然后遵循下边的游戏规则。
50+
51+
将数组中的每一个数字看成队伍编号。
52+
53+
`group1``group2` 首先初始化为不可能和当前数字相等的两个数,将这两个队伍看成同盟,它俩不互相伤害。
54+
55+
然后遍历数组中的其他数字,如果遇到的数字属于其中的一个队伍,就将当前队伍的数量加 `1`
56+
57+
如果某个队伍的数量变成了 `0`,就把这个队伍编号更新为当前的数字。
58+
59+
否则的话,将两个队伍的数量都减 `1`
60+
61+
```java
62+
public List<Integer> majorityElement(int[] nums) {
63+
int n = nums.length;
64+
long group1 = (long)Integer.MAX_VALUE + 1;
65+
int count1 = 0;
66+
long group2 = (long)Integer.MAX_VALUE + 1;
67+
int count2 = 0;
68+
for (int i = 0; i < n; i++) {
69+
if (nums[i] == group1) {
70+
count1++;
71+
} else if (nums[i] == group2) {
72+
count2++;
73+
} else if (count1 == 0) {
74+
group1 = nums[i];
75+
count1 = 1;
76+
} else if (count2 == 0) {
77+
group2 = nums[i];
78+
count2 = 1;
79+
} else {
80+
count1--;
81+
count2--;
82+
}
83+
}
84+
85+
//计算两个队伍的数量,因为可能只存在一个数字的数量超过了 n/3
86+
count1 = 0;
87+
count2 = 0;
88+
for (int i = 0; i < n; i++) {
89+
if (nums[i] == group1) {
90+
count1++;
91+
}
92+
if (nums[i] == group2) {
93+
count2++;
94+
}
95+
}
96+
//只保存数量大于 n/3 的队伍
97+
List<Integer> res = new ArrayList<>();
98+
if (count1 > n / 3) {
99+
res.add((int) group1);
100+
}
101+
102+
if (count2 > n / 3) {
103+
res.add((int) group2);
104+
}
105+
return res;
106+
}
107+
```
108+
109+
上边有个技巧就是先将 `group` 初始化为一个大于 `int` 最大值的 `long` 值,这样可以保证后边的 `if` 条件判断中,数组中一定不会有数字和 `group`相等,从而进入后边的更新队伍编号的分支中。除了用 `long` 值,我们还可以用包装对象 `Integer`,将 `group` 初始化为 `null` 可以达到同样的效果。
110+
111+
当然,不用上边的技巧也是可以的,我们可以先在 `nums` 里找到两个不同的值分别赋值给 `group1``group2` 中即可,只不过代码上不会有上边的简洁。
112+
113+
#
114+
115+
解法一算是通用的解法,解法二的话看起来比较容易,但如果只看上边的解析,然后自己写代码的话还是会遇到很多问题的,其中 `if` 分支的顺序很重要。

0 commit comments

Comments
 (0)