本文最后更新于:2025-02-21T22:24:26+08:00
给你一个未排序的整数数组 nums
,请你找出其中没有出现的最小的正整数。
请你实现时间复杂度为 O(n)
并且只使用常数级别额外空间的解决方案。
示例 1:
1 2 3
| 输入:nums = 输出:3 解释:范围 中的数字都在数组中。
|
示例 2:
1 2 3
| 输入:nums = [3,4,-1,1] 输出:2 解释:1 在数组中,但 2 没有。
|
示例 3:
1 2 3
| 输入:nums = [7,8,9,11,12] 输出:1 解释:最小的正数 1 没有出现。
|
提示:
1 <= nums.length <= 105
-231 <= nums[i] <= 231 - 1
题目思路
由于题目要求我们**「只能使用常数级别的空间」**,而要找的数一定在[1, N + 1]左闭右闭(这里N是数组的长度)这个区间里。因此,我们可以就把原始的数组当做哈希表来使用。事实上,哈希表其实本身也是一个数组;
我们要找的数就在[1, N + 1]里,最后N + 1这个元素我们不用找。因为在前面的N个元素都找不到的情况下,我们才返回N + 1;
那么,我们可以采取这样的思路:就把1这个数放到下标为0的位置,2这个数放到下标为1的位置,按照这种思路整理一遍数组。然后我们再遍历一次数组,第1个遇到的它的值不等于下标的那个数,就是我们要找的缺失的第一个正数。
这个思想就相当于我们自己编写哈希函数,这个哈希函数的规则特别简单,那就是数值为i的数映射到下标为i - 1的位置。
图解


题解代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
|
public int firstMissingPositive(int[] nums) { int[] array = Arrays.stream(nums).distinct().filter(x -> x > 0).sorted().toArray(); for (int i = 0; i < array.length; i++) { if (array[i] - 1 != i) { return i + 1; } } return array.length + 1; }
public int firstMissingPositive2(int[] nums) { for (int i = 0; i < nums.length; i++) { while (nums[i] > 0 && nums[i] <= nums.length && nums[nums[i] - 1] != nums[i]) { swap(nums, i, nums[i] - 1); } } for (int i = 0; i < nums.length; i++) { if (nums[i] - 1 != i) { return i + 1; } } return nums.length + 1; }
private void swap(int[] nums, int i, int j) { int t = nums[i]; nums[i] = nums[j]; nums[j] = t; }
|