LeetCode 41. 缺失的第一个正数

给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。

请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。

示例 1:

输入:nums = [1,2,0]
输出:3
解释:范围 [1,2] 中的数字都在数组中。

示例 2:

输入:nums = [3,4,-1,1]
输出:2
解释:1 在数组中,但 2 没有。

示例 3:

输入:nums = [7,8,9,11,12]
输出:1
解释:最小的正数 1 没有出现。

提示:

  • 1 <= nums.length <= 105
  • -231 <= nums[i] <= 231 - 1

思路

约束:

  1. 未排序 要求O(n) 不能使用排序算法 且对顺序有一定要求 考虑哈希表(集合)
  2. 常数级别的空间 不能使用哈希表(集合)

分析:

​ 考虑答案范围,最小值可能是1,如所有数都大于1;当nums[i]=i+1时,答案取最大值,最大值是nums.size+1。故答案范围在[1,nums.size+1]。所以只需要从小到大遍历该范围,第一个未出现的数字就是答案。

​ 考虑如果范围内某一数值x出现,则记录该值出现,自然想到集合或者哈希

难点:需要哈希表(集合),但不能使用哈希表(集合)

解决:

​ 如何记录?利用nums数组,[1,nums.size+1] 需要n个位置记录,所以让nums[i]记录i-1是否出现

​ 如果x在范围里,则用nums[x-1]保存该数字,原来的数据怎么办?将二者位置交换即可,交换之后,新数据有两种情况,在范围内,则需要继续交换,出现循环,考虑该操作有可能不停止吗,考虑一直在范围内的情况,也就是换了之后,目标位置符合条件nums[x-1]=x,同时本来的位置数值换过去也符合,也就是nums[i]=x, 出现了重复的数字,需要考虑该情况;不在范围内则停止处理。

eg: [3,4,1,-1]

i=0

​ 第一次交换 [1,4,3,-1]

交换后1在范围内,继续交换[1,4,3,-1] (其实1已经在位置上了,可以省略)

​ 交换后1在范围内,nums[0]=1,不需要继续交换

i=1

​ 第一次交换[1,-1,3,4]

i=2

i=3

结果[1,-1,3,4]

遍历结果 第一个不符合 nums[i]!=i+1的 i+1就是答案

实现:

int firstMissingPositive(vector<int>& nums) {
    for(int i=0;i<nums.size();i++) {
        //进行哈希
        while(nums[i]>0&&nums[i]<=nums.size()&&nums[i]!=i+1) {
            int t = nums[i];
            //需要考虑的死循环情况
            if(nums[i]==nums[t-1])
                break;
            nums[i]=nums[t-1];
            nums[t-1] = t;
        }
    }
    for(int i=0;i<nums.size();i++) {
        //找到第一个不符合条件的就是答案
        if(nums[i]!=i+1) {
            return i+1;
        }
    }

    return nums.size()+1;

}
posted @   ShacooKL  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· [翻译] 为什么 Tracebit 用 C# 开发
· 腾讯ima接入deepseek-r1,借用别人脑子用用成真了~
· Deepseek官网太卡,教你白嫖阿里云的Deepseek-R1满血版
· DeepSeek崛起:程序员“饭碗”被抢,还是职业进化新起点?
· RFID实践——.NET IoT程序读取高频RFID卡/标签
点击右上角即可分享
微信分享提示