缺失的第一个正数
给你一个未排序的整数数组 nums
,请你找出其中没有出现的最小的正整数。
请你实现时间复杂度为 O(n)
并且只使用常数级别额外空间的解决方案。
示例 1:
1 2 3
| 输入:nums = [1,2,0] 输出:3 解释:范围 [1,2] 中的数字都在数组中。
|
示例 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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class Solution { public int firstMissingPositive(int[] nums) { Map<Integer, Boolean> map = new HashMap<>(); int n = nums.length; int max = nums[0]; for (int i = 0; i < n; i++) { max = Math.max(max, nums[i]); if (nums[i] > 0) { map.put(nums[i], true); } } for (int i = 1; i <= max; i++) { if (!map.containsKey(i)) { return i; } } return max > 0 ? max + 1 : 1; } }
|
但是题目要求不能使用额外空间。使用现成的空间nums作为哈希表
映射规则是nums[i]
放在nums[i]-1
位置上 0 1 2 3
例如:nums = [3,4,-1,1]
把这个调整之后,变成nums = [1,-1,3,4]
调整方法就是不断交换位置。
当nums[i]-1!=i
时,就找到了答案
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
| class Solution { public int firstMissingPositive(int[] nums) { int n = nums.length; for (int i = 0; i < n; i++) { while (nums[i] > 0 && nums[i] < n && nums[i] != nums[nums[i] - 1]) { swap(nums, i, nums[i] - 1); } } for (int i = 0; i < n; i++) { if (nums[i] != i + 1) { return i + 1; } } return n + 1; }
private void swap(int[] nums, int a, int b) { int t = nums[a]; nums[a] = nums[b]; nums[b] = t; } }
|