当前位置: 首页 > article >正文

每日一题——数组中出现次数超过一半的数字

数组中出现次数超过一半的数字

    • 题目描述
      • 数据范围
    • 输入描述
    • 输出描述
    • 示例
      • 示例1
      • 示例2
      • 示例3
    • 题解
      • 解题思路
      • 摩尔投票算法
        • 步骤:
      • 代码实现
      • 代码解析
      • 时间与空间复杂度

题目描述

给定一个长度为 n 的数组,数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。

例如,输入一个长度为9的数组 [1, 2, 3, 2, 2, 2, 5, 4, 2]。由于数字 2 在数组中出现了5次,超过数组长度的一半,因此输出 2

数据范围

  • 数组长度:n ≤ 50000
  • 数组元素值:0 ≤ val ≤ 10000
  • 要求空间复杂度:O(1)
  • 时间复杂度:O(n)

输入描述

  • 输入保证数组非空,且保证有解。

输出描述

  • 输出数组中出现次数超过一半的数字。

示例

示例1

输入:

[1,2,3,2,2,2,5,4,2]

返回值:

2

示例2

输入:

[3,3,3,3,2,2,2]

返回值:

3

示例3

输入:

[1]

返回值:

1

题解

解题思路

本题的关键在于找出数组中出现次数超过一半的数字。我们可以使用 摩尔投票算法 来高效解决这个问题。该算法的时间复杂度为 O(n),且空间复杂度为 O(1)

摩尔投票算法

摩尔投票算法的核心思想是通过对数组进行两次扫描,首先确定一个候选元素,然后验证这个候选元素是否满足条件。

步骤:
  1. 第一遍扫描:我们用一个变量 candidate 来记录候选的数字,同时用一个 count 来记录当前候选数字的计数。如果遇到相同的数字,count 增加;如果遇到不同的数字,count 减少。当 count 为 0 时,更新 candidate 为当前数字,并重置 count 为 1。

  2. 第二遍扫描:验证 candidate 是否真的超过了数组长度的一半。如果是,返回该数字,否则返回其他错误值(但本题保证必定有解)。

代码实现

#include <vector>
#include <iostream>
using namespace std;

int majorityElement(vector<int>& nums) {
    int candidate = -1, count = 0;

    // 第一遍扫描,找出候选元素
    for (int num : nums) {
        if (count == 0) {
            candidate = num;
            count = 1;
        } else if (num == candidate) {
            count++;
        } else {
            count--;
        }
    }

    // 第二遍扫描,确认候选元素是否为多数元素
    count = 0;
    for (int num : nums) {
        if (num == candidate) {
            count++;
        }
    }

    return count > nums.size() / 2 ? candidate : -1; // 返回候选元素
}


代码解析

  • 第一遍扫描:我们首先设定 candidate 为 -1,表示当前还没有候选数字。count 用来计数,初始值为 0。在遍历数组时,遇到与 candidate 相同的数字时增加 count,否则减少 count。当 count 为 0 时,说明当前数字可以成为候选数字,重置 candidate 为当前数字,count 为 1。

  • 第二遍扫描:确认 candidate 是否真的是出现次数超过数组一半的数字。我们遍历数组,统计 candidate 的出现次数,最后检查它是否大于数组长度的一半。

时间与空间复杂度

  • 时间复杂度O(n),需要两次遍历数组,分别为找候选数字和验证候选数字。
  • 空间复杂度O(1),只用了常数空间来存储候选元素和计数。

http://www.kler.cn/a/539351.html

相关文章:

  • 一文学会:用DeepSeek R1/V3 + AnythingLLM + Ollama 打造本地化部署的个人/企业知识库,无须担心数据上传云端的泄露问题
  • Nginx部署Umi React前端项目标准配置
  • Qt之设置QToolBar上的按钮样式
  • 功能架构元模型
  • 09vue3实战-----引入element-plus组件库中的图标
  • LM Studio 部署本地大语言模型
  • 生成式聊天机器人 -- 基于Pytorch + Global Attention + 双向 GRU 实现的SeqToSeq模型 -- 下
  • AI安全最佳实践:AI云原生开发安全评估矩阵(下)
  • ESP32S3基于espidf ADC使用
  • Leetcode Hot100 76-80
  • 【算法-动态规划】、子序列累加和必须被7整除的最大累加和
  • 机器学习 网络安全 GitHub 机器人网络安全
  • 工业 4G 路由器助力消防领域,守卫生命安全防线
  • ASP.NET Core SignalR的分布式部署
  • 【Uniapp-Vue3】UniCloud云数据库获取指定字段的数据
  • 【蓝桥杯嵌入式】8_IIC通信-eeprom读写
  • 【Android开发AI实战】选择目标跟踪基于opencv实现——运动跟踪
  • 硬盘会莫名增加大量视频和游戏的原因
  • MoMask:可将文本描述作为输入并生成相应的高质量人体运动动作
  • 三种Excel文本连接方法!
  • C#Halcon窗体鼠标交互生成菜单
  • Android网络优化之-HTTPDNS
  • PHP-trim
  • 2025_2_9 C语言中队列
  • Docker 部署 RabbitMQ | 自带延时队列
  • leetcode 做题思路快查