Leetcode-41. 缺失的第一个正数

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

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

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

示例 3:
输入: [7,8,9,11,12]
输出: 1

提示:

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

来源:力扣(LeetCode)

分析

这道题最容易想到的办法是哈希表。但题目要求了不能用额外的空间,所以我们需要自己构造一个哈希表

首先遍历数组,如果数组里没有1,直接返回1。

如果有1,那么就把所有小于等于0和大于n的数字全都变为1。

(因为这道题的结果一定在1到n+1之间产生,别的数字可以直接不考虑,n+1的特殊情况我们放到后面说)

此时所有数字都为正而且在1到n之间,然后就到了最核心的构造哈希表环节了:我们用这些数字减1的值作为下标去寻找数字。具体实现如下:

遍历数组,把遍历到的数字作为索引,把该索引-1的位置取负。比如数组现在是[3,4,1,1]。遍历第一次把第三个数字(3-1=2,下标为2的数字)变为-1,数组变为[3,4,-1,1];第二次把第四个数字(4-1=3)变为-1,数组变为[3,4,-1,-1];注意到第三次nums[2]变为-1了,因此要有一个取绝对值的操作,把第一个数字(|-1|-1=0)变为-3,数组变为[-3,4,-1,-1];最后一次,此时第一个数字已经是负了,我们要保证这些数字只被改一次。上面的操作变为代码只需要下面两句

for(int i=0;i<n;i++){
	int a=Math.abs(nums[i])-1;
	nums[a]=-Math.abs(nums[a]);
}

最后,我们发现凡是没有的数字,对应下标的数字都是正数。比如没有2,即第二个数字4是正数。我们最后遍历数组,找到第一个是正数的数字返回索引即可。

最后的最后,注意一种特殊情况,比如[1,2,3,4]。最后的结果一定所有数字都是负数,这种情况我们返回n+1即可。代码如下:

class Solution {
    public int firstMissingPositive(int[] nums) {
        int n=nums.length;
        boolean exist1=false;
        for(int i=0;i<n;i++){
            if(nums[i]==1)
                exist1=true;
        }
        if(exist1==false)
            return 1;
        for(int i=0;i<n;i++){
            if(nums[i]<=0||nums[i]>n)
                nums[i]=1;
        }
        for(int i=0;i<n;i++){
            int a=Math.abs(nums[i])-1;
            nums[a]=-Math.abs(nums[a]);
        }
        for(int i=0;i<n;i++){
            if(nums[i]>0)
                return i+1;
        }
        return n+1;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值