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

每日一题——缺失的第一个正整数

缺失的第一个正整数

    • 题目描述
      • 进阶:
      • 数据范围:
    • 示例
      • 示例 1
      • 示例 2
      • 示例 3
    • 题解
      • 思路
      • 代码实现
      • 代码解释
      • 复杂度分析
      • 总结

题目描述

给定一个无重复元素的整数数组 nums,请你找出其中没有出现的最小的正整数。

进阶:

  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

数据范围:

  • 数组元素 nums[i] 的值在 − 2 31 ≤ n u m s [ i ] ≤ 2 31 − 1 -2^{31} \leq nums[i] \leq 2^{31} - 1 231nums[i]2311 之间。
  • 数组长度 len(nums) 满足 0 ≤ l e n ( n u m s ) ≤ 5 × 1 0 5 0 \leq len(nums) \leq 5 \times 10^5 0len(nums)5×105

示例

示例 1

输入:

[1, 0, 2]

输出:

3

示例 2

输入:

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

输出:

2

示例 3

输入:

[4, 5, 6, 8, 9]

输出:

1

题解

本题的关键点是寻找数组中最小的缺失正整数。由于数组中没有重复的元素,我们可以利用数组下标和数值之间的关系来进行处理。具体步骤如下:

思路

  1. 无效值处理

    • 数组中值小于等于0或大于数组长度的数值不可能是我们要找的最小正整数,可以将它们替换为一个不会影响结果的数字(例如 numsSize + 1)。
  2. 就地交换

    • 数组中的每个数字应该位于它应处的位置。例如,数字 1 应该位于索引 0,数字 2 应该位于索引 1,以此类推。
    • 我们通过交换将数字放到正确的位置上。
  3. 查找缺失的最小正整数

    • 遍历数组,找到第一个没有正确放置的数字,返回它的索引对应的正整数。
    • 如果所有的数字都正确放置了,说明数组中包含了所有从 1numsSize 的正整数,那么最小缺失正整数为 numsSize + 1

代码实现

#include <stdio.h>
#include <stdlib.h>

/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * @param nums int整型一维数组 
 * @param numsLen int nums数组长度
 * @return int整型
 */
int minNumberDisappeared(int* nums, int numsLen) {
    
    // 1. 将所有不合法的数值替换为 numsLen + 1
    for (int i = 0; i < numsLen; i++) {
        if (nums[i] <= 0 || nums[i] > numsLen) {
            nums[i] = numsLen + 1;
        }
    }

    // 2. 将每个数值放到它应该在的位置上
    for (int i = 0; i < numsLen; i++) {
        int num = abs(nums[i]);  // 获取当前值的绝对值
        if (num <= numsLen && nums[num - 1] > 0) {
            nums[num - 1] = -nums[num - 1]; // 标记 num 已经出现
        }
    }

    // 3. 查找第一个没有标记的正整数
    for (int i = 0; i < numsLen; i++) {
        if (nums[i] > 0) {
            return i + 1; // 返回缺失的第一个正整数
        }
    }

    // 4. 如果没有缺失,返回 numsSize + 1
    return numsLen + 1;
}


代码解释

  1. 无效值处理

    if (nums[i] <= 0 || nums[i] > numsLen) {
        nums[i] = numsLen + 1;
    }
    
    • 将数组中所有小于等于0或大于 numsLen 的数值替换为 numsLen + 1,因为这些数值不可能是我们要找的最小正整数。
  2. 就地交换

    int num = abs(nums[i]);
    if (num <= numsLen && nums[num - 1] > 0) {
        nums[num - 1] = -nums[num - 1]; // 标记为已出现
    }
    
    • 对于每个数字 num,我们将它放到应该在的位置(即 num-1 的位置)。如果 num 在数组范围内并且当前位置的数字是正数,就将该位置标记为负数,表示该数值已出现。
  3. 查找缺失的最小正整数

    if (nums[i] > 0) {
        return i + 1; // 返回缺失的第一个正整数
    }
    
    • 如果遍历完数组后,遇到第一个正数,说明该索引对应的正整数是缺失的最小正整数。
  4. 返回结果

    • 如果所有 1numsLen 的整数都已经出现,则返回 numsLen + 1

复杂度分析

  • 时间复杂度O(n),其中 n 是数组的长度。我们遍历数组三次:一次处理无效值,一次进行就地交换,一次查找缺失的最小正整数。
  • 空间复杂度O(1),除了输入数组外,没有使用额外的空间,所有操作都在原数组上进行。

总结

难得的一道简单的题目。。


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

相关文章:

  • 软考高级《系统架构设计师》知识点(一)
  • 机器学习 - 理解偏差-方差分解
  • PyQt学习记录
  • ArgoCD实战指南:GitOps驱动下的Kubernetes自动化部署与Helm/Kustomize集成
  • 深度学习-语音转文字
  • Java 中 ArrayList 和 LinkedList 有什么区别?
  • Open-Interface:基于大语言模型 LLM 的自动化界面操作系统
  • 前端开发中,如何判断一个元素是否在可视区域中?
  • ZND网络分析仪,一款高性能的测试与测量设备
  • 10:超级玛丽游戏
  • 利用NestJS构建高效的RESTful API接口
  • 什么是推理大模型?DeepSeek R1推理大模型与DeepSeek V3模型的区别是什么?什么时候该使用推理大模型?
  • 【Linux】:Socket编程应用层 TCP
  • [学习笔记] Kotlin Compose-Multiplatform
  • 在离线的服务器上部署Python的安装库
  • 计算机网络结课设计:通过思科Cisco进行中小型校园网搭建
  • kbengine服务器和 数据库 系统路径配置
  • C语言基本概念————讨论sqrt()和pow()函数与整数的关系
  • 高效利用Java爬虫开发批量获取商品信息:电商数据挖掘的“利器”
  • 【鸿蒙HarmonyOS Next实战开发】多媒体视频播放-GSYVideoPlayer
  • Pyqt的QTabWidget组件
  • 【STM32H743】【RT-Thread Studio】RTC功能(基于BSP工程可一键开启)
  • 嵌入式linux系统中VIM编辑工具用法与GCC参数详解
  • 记录一次报错:spring security 403报错
  • HIVE如何注册UDF函数
  • 使用 Python/Boto/Django 实现 S3 直接上传