8找出整形数组中超过一半的数 | 豆包MarsCode AI刷题

71 阅读4分钟

问题描述

小R从班级中抽取了一些同学,每位同学都会给出一个数字。已知在这些数字中,某个数字的出现次数超过了数字总数的一半。现在需要你帮助小R找到这个数字。


测试样例

样例1:

输入:array = [1, 3, 8, 2, 3, 1, 3, 3, 3]
输出:3

样例2:

输入:array = [5, 5, 5, 1, 2, 5, 5]
输出:5

样例3:

输入:array = [9, 9, 9, 9, 8, 9, 8, 8]
输出:9

9e9c3a09d72766b127ab15b068d9a28.png def solution(array): # 摩尔投票算法 candidate = None count = 0

for num in array:
    if count == 0:
        candidate = num
        count = 1
    elif num == candidate:
        count += 1
    else:
        count -= 1

# 验证 candidate 是否真的是众数
count = sum(1 for num in array if num == candidate)
if count > len(array) // 2:
    return candidate
else:
    return None

if name == "main": # 测试用例 print(solution([1, 3, 8, 2, 3, 1, 3, 3, 3])) # 输出: 3 print(solution([5, 5, 5, 1, 2, 5, 5])) # 输出: 5 print(solution([9, 9, 9, 9, 8, 9, 8, 8])) # 输出: 9 ### 问题描述解析

小R从班级中抽取了一些同学,每位同学都会给出一个数字。已知在这些数字中,某个数字的出现次数超过了数字总数的一半。现在需要你帮助小R找到这个数字。

解题思路

这个问题可以通过 摩尔投票算法(Boyer-Moore Voting Algorithm)来解决。摩尔投票算法的核心思想是在一次遍历中找到一个可能的众数候选,然后再在一次遍历中验证该候选是否确实是众数。具体步骤如下:

  1. 选择候选众数

    • 遍历数组,维护一个候选众数 candidate 和一个计数器 count
    • 如果 count 为 0,选择当前数字作为新的 candidate,并将 count 设为 1。
    • 如果当前数字等于 candidate,则 count 增加 1。
    • 如果当前数字不等于 candidate,则 count 减少 1。
  2. 验证候选众数

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

代码解析

函数定义

def solution(array):
    # 摩尔投票算法
    candidate = None
    count = 0
    
    for num in array:
        if count == 0:
            candidate = num
            count = 1
        elif num == candidate:
            count += 1
        else:
            count -= 1
    
    # 验证 candidate 是否真的是众数
    count = sum(1 for num in array if num == candidate)
    if count > len(array) // 2:
        return candidate
    else:
        return None

**

选择候选众数

    candidate = None
    count = 0
    
    for num in array:
        if count == 0:
            candidate = num
            count = 1
        elif num == candidate:
            count += 1
        else:
            count -= 1

**

  • 初始化 candidate 为 Nonecount 为 0。

  • 遍历数组 array 中的每个数字 num

    • 如果 count 为 0,表示当前没有候选众数,选择 num 作为新的 candidate,并将 count 设为 1。
    • 如果 num 等于 candidate,增加 count 的值。
    • 如果 num 不等于 candidate,减少 count 的值。

验证候选众数

    count = sum(1 for num in array if num == candidate)
    if count > len(array) // 2:
        return candidate
    else:
        return None

**

  • 再次遍历数组 array,统计 candidate 的出现次数。
  • 使用 sum(1 for num in array if num == candidate) 来计算 candidate 的出现次数。
  • 如果 candidate 的出现次数大于数组长度的一半,则返回 candidate
  • 否则,返回 None

测试样例解析

  1. 样例1

    • 输入:array = [1, 3, 8, 2, 3, 1, 3, 3, 3]

    • 输出:3

    • 解析:

      • 第一次遍历:

        • num = 1count = 1candidate = 1
        • num = 3count = 0candidate = 3
        • num = 8count = 0candidate = 8
        • num = 2count = 0candidate = 2
        • num = 3count = 0candidate = 3
        • num = 1count = 0candidate = 1
        • num = 3count = 0candidate = 3
        • num = 3count = 1candidate = 3
        • num = 3count = 2candidate = 3
      • 第二次遍历验证:

        • 3 的出现次数为 5,超过数组长度 9 的一半,因此返回 3
  2. 样例2

    • 输入:array = [5, 5, 5, 1, 2, 5, 5]

    • 输出:5

    • 解析:

      • 第一次遍历:

        • num = 5count = 1candidate = 5
        • num = 5count = 2candidate = 5
        • num = 5count = 3candidate = 5
        • num = 1count = 2candidate = 5
        • num = 2count = 1candidate = 5
        • num = 5count = 2candidate = 5
        • num = 5count = 3candidate = 5
      • 第二次遍历验证:

        • 5 的出现次数为 4,超过数组长度 7 的一半,因此返回 5
  3. 样例3

    • 输入:array = [9, 9, 9, 9, 8, 9, 8, 8]

    • 输出:9

    • 解析:

      • 第一次遍历:

        • num = 9count = 1candidate = 9
        • num = 9count = 2candidate = 9
        • num = 9count = 3candidate = 9
        • num = 9count = 4candidate = 9
        • num = 8count = 3candidate = 9
        • num = 9count = 4candidate = 9
        • num = 8count = 3candidate = 9
        • num = 8count = 2candidate = 9
      • 第二次遍历验证:

        • 9 的出现次数为 5,超过数组长度 8 的一半,因此返回 9

总结

摩尔投票算法通过两次遍历数组,第一次寻找可能的众数候选,第二次验证该候选是否确实是众数。该算法的时间复杂度为 O(n),空间复杂度为 O(1),非常高效地解决了众数问题。