摩尔投票算法¶
概述¶
摩尔投票算法(Boyer-Moore Majority Vote Algorithm)是一种高效的算法,用于在**O(n)时间**和**O(1)空间**内找出数组中出现次数超过⌊n/2⌋的元素(众数)。该算法由Robert S. Boyer和J Strother Moore于1981年提出。
摩尔投票的精妙之处
摩尔投票算法的核心思想是"抵消"——不同元素相互抵消,最终剩下的就是众数。它只需要常数空间,是解决众数问题的最优算法。
算法思想详解¶
投票抵消原理¶
graph TB
A["候选元素 candidate"] --> B["计数器 count"]
B --> C{"遇到新元素"}
C -->|与candidate相同| D["count++"]
C -->|与candidate不同| E["count--"]
E --> F{"count == 0?"}
F -->|是| G["更换candidate"]
F -->|否| H["继续"]
D --> I["继续"]
G --> B
style A fill:#E3F2FD
style G fill:#E8F5E9
核心思想¶
将数组中的元素分为两类: - 众数x:出现次数 > n/2 - 其他元素:出现次数 < n/2
抵消策略:每遇到一个非众数元素,就消耗一个众数元素。由于众数数量超过一半,最终必然剩下众数。
| Text Only | |
|---|---|
算法可视化演示¶
完整投票过程¶
抵消原理图解¶
graph TB
subgraph "抵消分组"
A["众数: 3,3,3,3"] --> B["非众数: 2,1,4"]
B --> C["相互抵消"]
C --> D["剩余: 3"]
end
style D fill:#E8F5E9
| Text Only | |
|---|---|
基本实现¶
C语言版本¶
验证结果¶
如果题目不保证众数一定存在,需要验证:
C++ 实现¶
扩展:求众数II(超过n/3)¶
问题分析¶
出现次数超过⌊n/3⌋的元素最多有**2个**。
实现¶
graph TB
subgraph "双候选摩尔投票"
A["维护两个候选 candidate1, candidate2"]
B["维护两个计数 count1, count2"]
C["遇到新元素时更新"]
D["最终验证两个候选"]
end
A --> B --> C --> D
style D fill:#E8F5E9
C++ 实现¶
扩展:求众数III(超过n/k)¶
通用实现¶
复杂度分析¶
时间复杂度¶
| 情况 | 时间复杂度 | 说明 |
|---|---|---|
| 摩尔投票 | O(n) | 遍历一次数组 |
| 验证结果 | O(n) | 再遍历一次验证 |
| 总计 | O(n) | 线性时间 |
空间复杂度¶
| 情况 | 空间复杂度 | 说明 |
|---|---|---|
| 超过n/2 | O(1) | 只需两个变量 |
| 超过n/3 | O(1) | 需要四个变量 |
| 超过n/k | O(k) | 最多k-1个候选 |
正确性证明¶
算法对比¶
| 方法 | 时间 | 空间 | 特点 |
|---|---|---|---|
| 摩尔投票 | O(n) | O(1) | 空间最优 |
| 哈希表 | O(n) | O(n) | 通用,易理解 |
| 排序 | O(n log n) | O(1) | 简单,但慢 |
| 分治 | O(n log n) | O(log n) | 递归思路 |
graph TB
A["找众数问题"] --> B["空间是否受限?"]
B -->|是| C["摩尔投票<br/>O n 时间, O 1 空间"]
B -->|否| D["数据是否有序?"]
D -->|是| E["二分查找<br/>O log n 时间"]
D -->|否| F["哈希表<br/>O n 时间, O n 空间"]
style C fill:#E8F5E9
应用场景¶
1. 投票系统¶
| C | |
|---|---|
2. 数据流中的主要元素¶
3. 实时监控系统¶
4. 内存受限的大数据处理¶
| C | |
|---|---|
常见变体问题¶
1. 检查是否是众数¶
| C | |
|---|---|
2. 找众数的索引¶
| C | |
|---|---|
3. 找众数的所有索引¶
| C | |
|---|---|
参考资料¶
- Boyer, R.S., & Moore, J.S. (1981). "MJRTY - A Fast Majority Vote Algorithm"
- 《算法导论》第9章 - 中位数和顺序统计量
- Boyer-Moore Majority Vote Algorithm - Wikipedia
- LeetCode 169. Majority Element
- LeetCode 229. Majority Element II