摩尔算法 | 豆包MarsCode AI刷题

71 阅读3分钟

基于豆包MarsCode AI的摩尔投票算法学习笔记:题目链接

摩尔投票算法(Moore Voting Algorithm)是一种用于寻找数组中多数元素的算法。多数元素是指在数组中出现次数超过一半的元素。摩尔算法因其简单且高效的特性而被广泛用于数据处理场景中。

核心思路

摩尔投票算法的核心思想是“抵消”原则。将数组中的每个元素视为一个选票,通过相互抵消的方式,最终留下的元素即为数组中的多数元素(如果存在)。这种思路利用了多数元素出现次数超过总数一半的特性,确保最终留下的元素一定是多数元素。

算法分为两个步骤:

  1. 候选人阶段:通过一次遍历找到一个“可能的候选多数元素”。
  2. 验证阶段:再次遍历数组,验证候选元素是否为多数元素。

候选人阶段

  • 初始时,没有候选人,计票值(count)为 0。
  • 遍历数组:
    • 如果 count 为 0,选择当前元素作为候选人,将 count 设为 1。
    • 如果当前元素等于候选人,count 增加 1。
    • 如果当前元素不等于候选人,count 减少 1。

这一阶段的作用是利用抵消的方式过滤掉非多数元素。

验证阶段

由于候选人阶段仅保证了候选人是可能的多数元素,需再次遍历数组以确认该候选人是否确实为多数元素(即,出现次数是否超过一半)。

示例摩尔算法

以下是一个示例数组:[3, 3, 4, 2, 4, 4, 2, 4, 4]。目标是找到多数元素。

1、候选人阶段:

  • 第一个元素为 3,设为候选人,count = 1
  • 第二个元素为 3,与候选人相同,count = 2
  • 第三个元素为 4,与候选人不同,count = 1
  • 第四个元素为 2,与候选人不同,count = 0
  • 第五个元素为 4,count = 1,候选人更改为 4。
  • 持续更新后,候选人为 4,count = 3

2、验证阶段:

  • 统计 4 的出现次数,共出现 5 次,占数组长度的一半以上。因此,多数元素为 4。

代码实现

int solution(vector<int> array) {
  // 摩尔投票算法
  int candidate = 0;
  int cnt = 0;
  for (auto a : array) {
    if (cnt == 0) {
      candidate = a;
      cnt = 1;
    } else if (candidate == a) {
      cnt++;
    } else if (candidate != a) {
      cnt--;
    }
  }
  return candidate;
}

个人理解

摩尔算法的巧妙之处在于“抵消”思想,避免了传统方法需要频繁计数的高开销操作。相比于直接统计每个元素出现次数,摩尔算法的时间复杂度为 O(n),且只需常数级空间,非常高效。

  • 时间复杂度:线性遍历,总时间复杂度为 O(n)。
  • 空间复杂度:常数级 O(1),仅使用少量变量。

在理解算法时,最关键的一点是认识到候选人阶段的过滤效果:只要存在多数元素,其在抵消后必然会“存活”。