leetcode 41. 缺失的第一个正数

### 题目

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

示例 1:

输入: [1,2,0]
输出: 3
示例 2:

输入: [3,4,-1,1]
输出: 2
示例 3:

输入: [7,8,9,11,12]
输出: 1
说明:

你的算法的时间复杂度应为O(n),并且只能使用常数级别的空间。

### 思路

因为是求缺失的第一个正数,也就是说求从1开始缺失的最小的整数,对于一个长度为n的数组,缺失的正数只有这样两种可能:

1、缺失的正数是1到n中的某一个数,具体不知道

2、如果1到n都没有缺失的数,那么缺失的那个最小的数就默认是n+1

那么问题就被清晰处理了,题目要求遍历一次数组,只需要在遍历数组的时候顺便对一个1到n长度的标志数组进行mark,到时候找到第一个未被mark的标志位置,就是缺失的第一个正数,如果都mark了,那么缺失的就是n+1,这样就解决了时间复杂度的要求。

但是空间复杂度只能使用常数空间,如果要设定一个上述的长度为n的标志数组,那么使用的就是n级别的空间,不是常数空间,考虑使用传进来的nums数组,原理是这样的,设定约束条件,在nums中,尽量让最多的nums[i]=i+1,这样在nums中,每个数字,如果它是在1到n之间的数,那么它一定有一个属于它的位置(不重复的情况下,如果重复,那么就不用将它放到按约束条件应该放的位置,放在原位即可),将它调整到它应该处于的位置,调整结束之后。找到第一个不满足nums[i]=i+1的位置,那么它就是缺失的第一个正数,例子如下:

[1,1]
nums[0]=0+1
nums[1]!=1+1,按照约束条件,nums[1]的值是1,应该放在nums[0]上,但是nums[0]已经放了一个正确的数,所以保持原位
找到第一个不满足nums[i]=i+1条件的元素的索引为1,所以输出结果2.

[3,4,-1,1]
nums[0]!=0+1,按照约束条件,nums[0]=3,3应该放在nums[2]的位置上,交换两者的值,这里注意,被交换过来的值位置肯定是不对的,因为位置正确的值不会被交换,所以要再次进行约束条件判定,交换来的值是-1,所以不用管。
nums[1]!=1+1,按照约束条件,4应该放在nums[3]的位置上,交换两者位置,然后得到nums[1]等于1,也是错误的位置,然后寻找1应该处于的位置,发现nums[0]=-1,也是错误的,交换nums[0] and nums[1],交换来的值是-1,不再1到n之间,不管。
nums[2]位置正确
nums[3]位置正确
最后nums={1,-1,3,4},第一个不满足条件的就是nums[1],所以输出2.

[1,2,4,3]
nums[0]、nums[1]位置正确
nums[2]位置不对,交换到nums[3],交换来的3再进行判断,位置正确。
nums[3]位置正确
最后nums={1,2,3,4},数组内没有不满足的,所以返回n+1,返回5.

### code

     

  class Solution {
        public:
          int firstMissingPositive(vector<int>& nums) {
                int n=nums.size();
                for(int i=0;i<n;++i)
                {
                    while (nums[i] > 0 && nums[i] <= n && nums[i] != nums[nums[i]-1])//交换到满足条件的位置
                     //并且判断交换而来的数是否依然满足条件。
                    {
                        swap(nums[i], nums[nums[i] - 1]);
                    }
                }
                for(int i=0;i<n;++i)//找出第一个不满足条件的数
                {
                    if(nums[i]!=i+1)
                        return i+1;
                }
                return n+1;//没有的情况下,输出n+1
                    
        }
        };

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值