缺失的第一个正数

103 阅读2分钟

这是我参与2022首次更文挑战的第6天,活动详情查看:2022首次更文挑战

leetcode 缺失的第一个正数

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

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

示例 1:

输入:nums = [1,2,0]
输出:3

示例 2:

输入:nums = [3,4,-1,1]
输出:2

示例 3:

输入:nums = [7,8,9,11,12]
输出:1
 ```
 




解题:
要在一个数组中找到其中未出现的最小正整数,这个数组还是未排序的,并且数组元素是无符号的,还要求时间复杂度为O(N),空间复杂度为 O(1)。很多限制条件了,时间复杂度的话,O(2N)也是O(N),O(3N)也是O(N),空间只能使用常数个了。根据这些条件可以将数组元素放入到哈希表中(因为哈希表查找元素的时间复杂度为O(1)),从1开始依次判断这个数是否在哈希表中,但是使用另外的哈希表就不满足空间复杂度的要求了,所以可以考虑直接使用原来的数组,将原数组当一个哈希表来使用,来记录一下状态。首先对于长度为L的数组,那这个最小的正整数肯定在[1,L+1]里面,数组只能有L个的元素,如果1到L的整数都出现了,那最小正整数就是L+1了,否则肯定有一个1到L的最小正整数没在数组里面。然后我们遍历数组元素,因为数组可能会有负数,所以得先将负数值都转成L+1,因为这些负数是不在[1, L]中的,可以不考虑,然后在遍历数组获取元素判断是否在[1,L]范围内,如果在那就将这个数+1的下标位置的元素改为负数,那么一直到最后再查询遍历数组元素,如果数组元素都是负数那最小正整数就是L+1,否则就是数组第一个正数的位置下标+1。



```js
class Solution {
    public int firstMissingPositive(int[] nums) {
        int len = nums.length;
        for (int i = 0; i < len; i++) {
            if (nums[i] <= 0) {
                nums[i] = len + 1;
            }
        }
        for (int i = 0; i < len; i++) {
            int num = Math.abs(nums[i]);
            if (num <= len) {
                nums[num - 1] = -Math.abs(nums[num - 1]);
            }
        }
        for (int i = 0; i < len; i++) {
            if (nums[i] > 0) {
                return i + 1;
            }
        }
        return len + 1;
    }
}