41. 缺失的第一个正数

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,0,3,1] 这个样例。这种写法的空间和时间都不符合题意

class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        auto num=unique(nums.begin(),nums.end());
        nums.erase(num,nums.end());
        //cout<<nums.size()<<endl;
        int ls=nums.size();
        int minnum=1;
        bool flag=false;
        int t=0;
        vector<int> w;
        for(int i=0;i<ls;i++){//保证非负
            if(nums[i]>0){
                t=i;
                flag=true;
                w.push_back(nums[i]);
            }
        }
        sort(w.begin(),w.end());
        int len=w.size();
        if(!flag||(len==1&&w[0]!=1)) return 1;//不存在非负,或者整个数组的长度只有1时
        for(int i=0;i<len;i++){
            if(w[i]==minnum){
                minnum++;
            }
            else if(w[i]!=minnum&&i+1==len)//处理数组的右边界
            {
                if(minnum+1<=nums[i]){
                    return minnum;
                }
                else{
                    return minnum++;
                }
            }
            else if(w[i]!=minnum&&i+1!=len){//处理中间部分缺失的情况
                break;
            }
        }
        return minnum;
    }
};

代码二
存在映射关系,设计哈希表,空间复杂度为O(1),将原数组设计成哈希表,负数换成n+1,这样的数不在考虑范围内,合理的处理了负数对于整个数组的影响,给正数打负号标记,来判断缺失哪个数

class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        int len=nums.size();
        for(int& num:nums){//处理负数的不合法
            if(num<=0){
                num=len+1;
            }
        }
        for(int i=0;i<len;i++){
            int num = abs(nums[i]);
            if(num<=len){
                nums[num-1] = -abs(nums[num-1]);
            }
        }
        for(int i=0;i<len;i++){
            if(nums[i]>0){
                return i+1;
            }
        }
        return len+1;
    }
};

代码三
找到最小的整数,可以不开新的空间的条件下,把数组中的正数放在合法位置,在进行遍历即可,需要注意的是有 nums[i]=x=nums[x−1]这个会陷入死循环,排除这个情况即可。

class Solution {   
public:   
    int firstMissingPositive(vector<int>& nums) {   
        int len = nums.size();   
        for (int i = 0; i < len; i++) {   
            while (nums[i] > 0 && nums[i] <= len && nums[nums[i] - 1] != nums[i]) {
            swap(nums[nums[i] - 1], nums[i]);   
            }
        }
        for (int i = 0; i < len; i++) {   
            if (nums[i] != i + 1) {   
                return i + 1;   
            }
        }
        return len + 1;   
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值