青训营X豆包MarsCode 技术训练营:找出整型数组中占比超过一半的数Python题解 | 豆包MarsCode AI 刷题

76 阅读2分钟

找出整型数组中占比超过一半的数

问题描述

小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

解题思路

这个问题可以通过 Boyer-Moore 投票算法(Boyer-Moore Voting Algorithm),即摩尔算法来解决。题目给定了一个整数数组,并保证有一个数的出现次数超过数组长度的一半。因为这个数的出现次数超过一半,所以它必然是数组中的众数,即出现次数最多的数。可以利用这个特性来找到它。

Boyer-Moore 投票算法的思路是通过“投票”来找出数组中的众数:

  1. 初始化一个候选数 candidate 和一个计数器 count

  2. 遍历数组中的每个数:

    • 如果 count 为 0,意味着之前的候选数被“投票”抵消完了,那么我们将当前数设为新的候选数,并将 count 设为 1。
    • 如果当前数等于候选数,则增加 count
    • 如果当前数不等于候选数,则减少 count
  3. 由于众数的出现次数超过一半,最后剩下的 candidate 必然是众数。

Python代码

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
    return candidate


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

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

关键代码解释

  • candidate = Nonecount = 0: 初始化候选数和计数器。在遍历数组之前,候选数为空且计数为 0。

  • if count == 0: 当计数器为 0 时,表示前面的候选数和其他数相互抵消。此时,将当前元素 num 设为新的候选数,并将 count 重置为 1。

  • elif num == candidate: 如果当前数 num 等于当前的候选数,则增加 count。因为该数支持候选数,所以增加计数。

  • else: count -= 1: 如果当前数 num 不等于候选数,则减少 count。这相当于“投反对票”。

时间和空间复杂度

  • 时间复杂度:O(n),其中 n 是数组的长度。遍历数组一次即可找出众数。
  • 空间复杂度:O(1),只需要常数级的额外空间来存储 candidatecount