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

81 阅读2分钟

问题描述

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

问题解析

  1. 给定一个数组,数组中的某个元素出现次数超过数组长度的一半。
  2. 找出这个多数元素。

关键点

  • 数组中一定存在一个多数元素,因为它的出现次数超过数组长度的一半。

这个问题是一个典型的“多数元素问题”,即在一个数组中找到出现次数超过数组长度一半的元素。代码实现采用的是一种高效算法——Boyer-Moore 投票算法

Boyer-Moore 投票算法详解

算法思路

  1. 核心原理

    • 如果我们假设多数元素存在,它的数量一定比其他所有元素的总和还要多。
    • 因此可以通过一个计数器和一个候选变量,不断筛选掉非多数元素,最终找到多数元素。
  2. 具体步骤

    • 初始化计数器 count = 0 和候选元素 candidate = 0

    • 遍历数组:

      1. 如果计数器为 0,将当前数字设置为候选元素,并将计数器置为 1
      2. 如果当前数字等于候选元素,则计数器加 1
      3. 如果当前数字不等于候选元素,则计数器减 1
    • 遍历结束后,candidate 中存储的就是多数元素。

为什么这样有效?

  • 假设数组长度为 n,多数元素出现次数超过 n/2。每次计数器减少时,实际上在筛掉非多数元素。因此多数元素的累计数量一定会支撑它成为最后的候选值。

Boyer-Moore 投票算法是解决“多数元素问题”的经典方法,利用“计数器”的机制高效找到多数元素。此实现具有以下特点:

  • 简单高效。
  • 时间复杂度为 O(n),空间复杂度为 O(1)。
  • 对于输入的合法性(如是否存在多数元素),题目保证了问题条件,因此无需额外验证。

代码实现

#include <iostream>
#include <vector>

using namespace std;

int solution(vector<int> array) {
    int count=0;
    int candidate=0;
    for(int num:array){
        if(count==0){
            candidate=num;
            count=1;
        }else if(num==candidate){
            count++;
        }else{
            count--;
        }
    } 
    return candidate;
}

int main() {
    cout << (solution({1, 3, 8, 2, 3, 1, 3, 3, 3}) == 3) << endl;
    cout << (solution({5, 5, 5, 1, 2, 5, 5}) == 5) << endl;
    cout << (solution({9, 9, 9, 9, 8, 9, 8, 8}) == 9) << endl;
    return 0;
}

关键步骤解释

  • 初始化

    • count 初始化为0,candidate 初始化为0。
  • 遍历数组

    • 对于每个数字 num,检查 count 是否为0。如果是,将 num 设为 candidate,并将 count 设为1。
    • 如果 num 与 candidate 相同,count 加1。
    • 如果 num 与 candidate 不同,count 减1。
  • 返回结果

    • 最终,candidate 就是我们要找的数字。