编号8题解 | 豆包MarsCode AI 刷题

179 阅读4分钟

题目描述

小R从班级中抽取了一些同学,每位同学都会给出一个数字。已知在这些数字中,某个数字的出现次数超过了数字总数的一半。现在需要你帮助小R找到这个数字。
例如,在数组 [1, 3, 8, 2, 3, 1, 3, 3, 3] 中,数字 3 出现了5次,超过了数组长度9的一半,因此答案是 3

解题思路

这个问题可以通过多种方法解决,但最高效的方法是使用 Boyer-Moore 投票算法。这个算法的时间复杂度为 O(n),空间复杂度为 O(1),非常适合解决这类问题。

Boyer-Moore 投票算法的核心思想
  1. 候选者选择:遍历数组,维护一个候选者 candidate 和一个计数器 count。初始时,将第一个元素设为候选者,计数器设为1。

  2. 计数器更新

    • 如果计数器为0,重新选择当前元素为新的候选者,并将计数器设为1。
    • 如果当前元素等于候选者,计数器加1。
    • 如果当前元素不等于候选者,计数器减1。
  3. 验证候选者:遍历数组,统计候选者的出现次数。如果候选者的出现次数超过数组长度的一半,则返回候选者;否则返回错误信息。

详细步骤

  1. 初始化

    • candidate:初始设为数组的第一个元素。
    • count:初始设为1。
  2. 第一次遍历数组

    • 遍历数组的每个元素。
    • 如果 count 为0,重新选择当前元素为新的候选者,并将 count 设为1。
    • 如果当前元素等于 candidate,将 count 加1。
    • 如果当前元素不等于 candidate,将 count 减1。
  3. 第二次遍历数组

    • 遍历数组,统计 candidate 的出现次数。
    • 如果 candidate 的出现次数超过数组长度的一半,返回 candidate

代码解析

def solution(array):
    # 初始化候选者和计数器
    candidate = array[0]
    count = 1

    # 第一次遍历数组,选择候选者
    for i in range(1, len(array)):
        if count == 0:
            candidate = array[i]
            count = 1
        elif array[i] == candidate:
            count += 1
        else:
            count -= 1

    # 第二次遍历数组,验证候选者
    count = 0
    for i in range(len(array)):
        if array[i] == candidate:
            count += 1

    # 返回候选者(题目保证一定存在这样的数字)
    return candidate

输入输出全过程分析实例

示例 1

输入数组[1, 3, 8, 2, 3, 1, 3, 3, 3]

  1. 初始化

    • candidate = 1
    • count = 1
  2. 第一次遍历数组

    • i = 1array[1] = 3count = 0,重新选择 candidate = 3count = 1
    • i = 2array[2] = 8count = 0,重新选择 candidate = 8count = 1
    • i = 3array[3] = 2count = 0,重新选择 candidate = 2count = 1
    • i = 4array[4] = 3count = 0,重新选择 candidate = 3count = 1
    • i = 5array[5] = 1count = 0,重新选择 candidate = 1count = 1
    • i = 6array[6] = 3count = 0,重新选择 candidate = 3count = 1
    • i = 7array[7] = 3count = 2
    • i = 8array[8] = 3count = 3
  3. 第二次遍历数组

    • 统计 candidate = 3 的出现次数,结果为5。
  4. 返回结果

    • return 3

输出3

示例 2

输入数组[2, 2, 1, 1, 1, 2, 2]

  1. 初始化

    • candidate = 2
    • count = 1
  2. 第一次遍历数组

    • i = 1array[1] = 2count = 2
    • i = 2array[2] = 1count = 1
    • i = 3array[3] = 1count = 0,重新选择 candidate = 1count = 1
    • i = 4array[4] = 1count = 2
    • i = 5array[5] = 2count = 1
    • i = 6array[6] = 2count = 0,重新选择 candidate = 2count = 1
  3. 第二次遍历数组

    • 统计 candidate = 2 的出现次数,结果为4。
  4. 返回结果

    • return 2

输出2

学习心得

  1. 算法选择的重要性:Boyer-Moore 投票算法是一个非常高效的算法,适用于寻找数组中出现次数超过一半的数字。它的时间复杂度为 O(n),空间复杂度为 O(1),非常适合处理大数据量的情况。
  2. 问题分解:将问题分解为候选者选择和验证两个步骤,可以使算法更加清晰和高效。
  3. 边界条件处理:虽然题目保证一定存在一个出现次数超过一半的数字,但在实际应用中,处理边界条件是非常重要的,可以增加代码的健壮性。