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

36 阅读4分钟

题目解析: 这是一道寻找数组中出现次数超过一半的元素(众数)的问题。关键特点是:

  1. 保证存在一个数字出现次数超过总数的一半
  2. 需要找到这个数字(而不是统计次数)
  3. 要求尽可能高效的解法

关键特征分析:

  1. 出现次数超过n/2的数字最多只能有一个
  2. 这个数字一定存在(题目保证)
  3. 不需要考虑特殊情况(如空数组)
  4. 不要求保持原数组顺序

解题思路分析:

  1. 基本解法思路(多种方案):

方案1:哈希表统计法

python
CopyInsert
def find_majority(array):
    count_dict = {}
    n = len(array)
    for num in array:
        count_dict[num] = count_dict.get(num, 0) + 1
        if count_dict[num] > n // 2:
            return num
    return array[0]  # 因为题目保证存在众数,所以一定会在循环中返回

方案2:排序法

python
CopyInsert
def find_majority(array):
    array.sort()
    return array[len(array) // 2]

方案3:摩尔投票法(最优解)

python
CopyInsert
def find_majority(array):
    candidate = array[0]
    count = 1
    
    # 找到候选众数
    for num in array[1:]:
        if count == 0:
            candidate = num
            count = 1
        elif num == candidate:
            count += 1
        else:
            count -= 1
    
    return candidate
  1. 各方案分析:

a) 哈希表统计法:

  • 优点:

    • 直观易理解
    • 实现简单
    • 只需要遍历一次数组
  • 缺点:

    • 需要额外空间存储计数
    • 不是最优的空间复杂度

b) 排序法:

  • 优点:

    • 实现最简单
    • 不需要额外的数据结构
  • 缺点:

    • 时间复杂度较高 O(nlogn)
    • 改变了原数组顺序

c) 摩尔投票法:

  • 优点:

    • 时间复杂度最优 O(n)
    • 空间复杂度最优 O(1)
    • 不改变原数组
  • 缺点:

    • 理解起来较难
    • 不直观
  1. 摩尔投票法详细解释:

原理:

  • 如果一个数出现次数超过n/2,那么它出现的次数减去其他所有数出现的次数仍然大于0

  • 可以把这个过程想象成一场选举:

    • 候选人获得一票就+1
    • 反对票就-1
    • 当计数为0时换新候选人
    • 最后留下的候选人一定是众数

算法步骤:

  1. 初始化第一个数为候选人,票数为1

  2. 遍历数组:

    • 如果当前票数为0,更换候选人
    • 如果当前数字等于候选人,票数+1
    • 如果当前数字不等于候选人,票数-1
  3. 最后剩下的候选人就是众数

算法复杂度分析:

  1. 摩尔投票法(最优解):

    • 时间复杂度:O(n)
    • 空间复杂度:O(1)
  2. 哈希表方法:

    • 时间复杂度:O(n)
    • 空间复杂度:O(n)
  3. 排序方法:

    • 时间复杂度:O(nlogn)
    • 空间复杂度:O(1)或O(n)(取决于排序算法)

需要注意的边界情况:

  1. 数组长度为1
  2. 所有元素相同
  3. 众数刚好占一半以上
  4. 数组中有负数

代码优化建议:

  1. 输入验证:

    • 检查数组是否为空
    • 检查数组长度是否合法
  2. 性能优化:

    • 使用摩尔投票法
    • 避免不必要的内存分配
  3. 代码可读性:

    • 添加适当的注释
    • 使用有意义的变量名
    • 模块化函数设计

实际应用场景:

  1. 投票系统
  2. 数据统计
  3. 模式识别
  4. 信号处理

测试用例设计:

  1. 基本测试:

    • 正常的数组输入
    • 不同大小的数组
    • 不同的众数值
  2. 边界测试:

    • 最小数组(一个元素)
    • 所有元素相同
    • 众数刚好超过一半
  3. 特殊测试:

    • 负数测试
    • 零值测试
    • 大数测试

总结: 这道题目的关键点在于:

  1. 理解问题特性(必定存在众数)
  2. 选择合适的算法(摩尔投票法最优)
  3. 正确处理边界情况
  4. 注意代码的可维护性

学习要点:

  1. 算法效率的权衡
  2. 空间复杂度的优化
  3. 代码实现的技巧
  4. 实际应用的考虑

这是一道很好的算法题,既可以训练基本编程能力,也能学习到优秀的算法思想。摩尔投票法的思想在其他类似问题中也有应用,值得深入理解。