Loading...

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

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

示例 1:

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

示例 2:

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

示例 3:

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

提示:

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

解法一

/**
 * 置换
 * 恢复数组,数组应当有 [1, 2, ..., N] 的形式,
 * 但其中有若干个位置上的数是错误的,每一个错误的位置就代表了一个缺失的正数。
 * 以题目中的示例二 [3, 4, -1, 1] 为例,恢复后的数组应当为 [1, -1, 3, 4],我们就可以知道缺失的数为 2。
 *
 * @param nums
 * @return
 */
public static int firstMissingPositive2(int[] nums) {
    int length = nums.length;
    for (int i = 0; i < length; i++){
        // 循环交换,直到当前位置为当前值
        while (nums[i] <= length && nums[i] > 0 && nums[nums[i] - 1] != nums[i]){
            int temp = nums[nums[i] - 1];
            nums[nums[i] - 1] = nums[i];
            nums[i] = temp;
        }
    }
    int result = 1;
    for (int i = 0; i < length; i++){
        if (nums[i] != result) break;
        result++;
    }
    return result;
}

题解二

/**
 * 哈希表
 * 我们将数组中所有小于等于 0 的数修改为 N+1;
 *
 * 我们遍历数组中的每一个数 x,它可能已经被打了标记,因此原本对应的数为 |x|,
 * 其中 || 为绝对值符号。如果 |x|∈[1,N],那么我们给数组中的第 |x|-1 个位置的数添加一个负号。注意如果它已经有负号,不需要重复添加;
 *
 * 在遍历完成之后,如果数组中的每一个数都是负数,那么答案是 N+1,否则答案是第一个正数的位置加 1。
 *
 * @param nums
 * @return
 */
public static int firstMissingPositive3(int[] nums) {
    int length = nums.length;
    for (int i = 0; i < length; i++){
        if (nums[i] <= 0) nums[i] = length + 1;
    }
    for (int i = 0; i < length; i++){
        int index = Math.abs(nums[i]);
        if (index <= length){
            nums[index - 1] = -Math.abs(nums[index - 1]);
        }
    }
    for (int i = 0; i < length; i++) {
        if (nums[i] > 0){
            return i + 1;
        }
    }
    return length + 1;
}

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/first-missing-positive