找出整型数组中占比超过一半的数 | 豆包MarsCode AI 刷题

84 阅读3分钟

问题描述

给定一个整型数组,其中某个数字的出现次数超过了数组长度的一半。我们的任务是找到这个数字。

摩尔投票法的基本思想

摩尔投票法的核心思想是通过抵消的方式找到数组中的多数元素。具体步骤如下:

  1. 初始化

    • 设置一个候选元素 candidate,初始值为 None
    • 设置一个计数器 count,初始值为 0。
  2. 第一遍遍历数组

    • 遍历数组中的每个元素。
    • 如果 count 为 0,将当前元素设为 candidate,并将 count 设为 1。
    • 如果当前元素等于 candidate,将 count 增加 1。
    • 如果当前元素不等于 candidate,将 count 减少 1。
  3. 第二遍遍历数组

    • 遍历数组,统计 candidate 的出现次数。
    • 如果 candidate 的出现次数超过数组长度的一半,返回 candidate
    • 否则,返回 None(虽然题目保证一定存在这样的元素,但这一步是为了完整性)。

详细步骤

第一遍遍历

假设数组为 [1, 3, 8, 2, 3, 1, 3, 3, 3],我们逐步执行第一遍遍历:

  1. 初始化:candidate = None, count = 0
  2. 遍历第一个元素 1
    • count == 0,所以 candidate = 1, count = 1
  3. 遍历第二个元素 3
    • 3 != 1,所以 count = 0
  4. 遍历第三个元素 8
    • count == 0,所以 candidate = 8, count = 1
  5. 遍历第四个元素 2
    • 2 != 8,所以 count = 0
  6. 遍历第五个元素 3
    • count == 0,所以 candidate = 3, count = 1
  7. 遍历第六个元素 1
    • 1 != 3,所以 count = 0
  8. 遍历第七个元素 3
    • count == 0,所以 candidate = 3, count = 1
  9. 遍历第八个元素 3
    • 3 == 3,所以 count = 2
  10. 遍历第九个元素 3
    • 3 == 3,所以 count = 3

经过第一遍遍历,candidate = 3count = 3

第二遍遍历

接下来,我们验证 candidate 是否确实是多数元素:

  1. 初始化 count = 0
  2. 遍历数组,统计 3 的出现次数:
    • 1 不是 3count = 0
    • 33count = 1
    • 8 不是 3count = 1
    • 2 不是 3count = 1
    • 33count = 2
    • 1 不是 3count = 2
    • 33count = 3
    • 33count = 4
    • 33count = 5

经过第二遍遍历,count = 5,大于数组长度的一半(9 / 2 = 4.5),因此 3 是多数元素。

完整代码

def solution(array):
    # Edit your code here

    candidate = None
    count = 0
    
    # 第一遍遍历,找到候选元素
    for num in array:
        if count == 0:
            candidate = num
            count = 1
        elif num == candidate:
            count += 1
        else:
            count -= 1
    
    # 第二遍遍历,验证候选元素是否确实是多数元素
    count = 0
    for num in array:
        if num == candidate:
            count += 1
    
    if count > len(array) // 2:
        return candidate
    else:
        return None  # 在题目保证一定存在的情况下,这行实际上不会被执行


if __name__ == "__main__":
    # Add your test cases here

    print(solution([1, 3, 8, 2, 3, 1, 3, 3, 3]) == 3)

总结

摩尔投票法通过抵消的方式高效地找到了数组中的多数元素。第一遍遍历用于找到候选元素,第二遍遍历用于验证候选元素是否确实是多数元素。这种方法的时间复杂度为 O(n),空间复杂度为 O(1),非常适合解决这类问题。