LeetCode 第 169 题「多数元素」
字数 1676 2025-10-27 12:40:10
好的,我们这次来详细讲解 LeetCode 第 169 题「多数元素」。
1. 题目描述
题目:给定一个大小为 n 的数组 nums,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例 1:
输入:nums = [3,2,3]
输出:3
示例 2:
输入:nums = [2,2,1,1,1,2,2]
输出:2
提示:
n == nums.length1 <= n <= 5 * 10^4-10^9 <= nums[i] <= 10^9
2. 题意理解
题目说“多数元素”出现次数 大于 n/2,这意味着:
- 它出现的次数比其他所有元素加起来还要多。
- 一定存在且只有一个这样的元素(题目已保证存在)。
所以我们要找的就是数组中的“众数”,并且它超过半数。
3. 思路演进
3.1 方法一:哈希表计数(最直观)
- 遍历数组,用哈希表记录每个数字出现的次数。
- 当某个数字的计数超过
n/2时,直接返回它。 - 时间复杂度:O(n)
- 空间复杂度:O(n)(最坏情况需要存储 n/2 个不同数字)
伪代码:
count_map = {}
for num in nums:
count_map[num] = count_map.get(num, 0) + 1
if count_map[num] > n/2:
return num
这个方法简单有效,但需要 O(n) 的额外空间。
3.2 方法二:排序法
- 将数组排序。
- 由于多数元素数量超过一半,那么排序后数组中间位置(下标
n//2)一定是多数元素。 - 时间复杂度:O(n log n)(由排序决定)
- 空间复杂度:O(1)(如果排序是原地排序)
示例:
nums = [2,2,1,1,1,2,2]
排序后:[1,1,1,2,2,2,2]
中间位置 index = 3 → nums[3] = 2
这个方法时间效率不如哈希表法,但代码简单。
3.3 方法三:Boyer-Moore 投票算法(最优解)
这是本题的经典 O(n) 时间、O(1) 空间的算法。
核心思想:
- 把多数元素记为
+1票,其他元素记为-1票。 - 由于多数元素数量超过一半,最终“正”票数会胜出。
算法步骤:
- 初始化候选元素
candidate和计数器count = 0。 - 遍历数组:
- 如果
count == 0,选择当前元素作为候选candidate。 - 如果当前元素等于
candidate,count++,否则count--。
- 如果
- 遍历结束后,
candidate就是多数元素(题目保证存在,所以无需再验证;如果题目不保证存在,需要再遍历一次验证)。
为什么可行?
- 对抗思想:不同元素互相抵消,由于多数元素数量超过一半,所以最后剩下的必然是多数元素。
4. 逐步推演示例
以 nums = [2,2,1,1,1,2,2] 为例,n=7,多数元素需出现至少 4 次。
| 步骤 | 当前数字 | candidate | count | 说明 |
|---|---|---|---|---|
| 初始 | - | 无 | 0 | |
| 1 | 2 | 2 | 1 | count=0,选2,count=1 |
| 2 | 2 | 2 | 2 | 等于2,count+1=2 |
| 3 | 1 | 2 | 1 | 不等于2,count-1=1 |
| 4 | 1 | 2 | 0 | 不等于2,count-1=0(抵消) |
| 5 | 1 | 1 | 1 | count=0,选1,count=1 |
| 6 | 2 | 1 | 0 | 不等于1,count-1=0(抵消) |
| 7 | 2 | 2 | 1 | count=0,选2,count=1 |
最终 candidate = 2,确实是多数元素。
5. 代码实现(Boyer-Moore 投票算法)
def majorityElement(nums):
candidate = None
count = 0
for num in nums:
if count == 0:
candidate = num
count += (1 if num == candidate else -1)
return candidate
6. 复杂度分析
- 时间复杂度:O(n),一次遍历。
- 空间复杂度:O(1),只用了两个变量。
7. 总结
- 本题展示了“空间最优”的投票算法,适用于找出现次数超过一半的元素。
- 如果题目不保证存在多数元素,需要第二次遍历验证 candidate 是否真的超过 n/2 次。
- 对比哈希表法,投票算法在空间上更优,适合大数据量场景。
这样讲解清楚了吗?我们可以继续下一个题目,或者你对这个题目的某部分还有疑问?