给你一个未排序的整数数组 nums
,请你找出其中没有出现的最小的正整数。
请你实现时间复杂度为 O(n)
并且只使用常数级别额外空间的解决方案。
提示:
1 <= nums.length <= 10^5
-2^31 <= nums[i] <= 2^31 - 1
哈希表存储
解:缺失的第一个正数一定会在[1, nums.length + 1]中,比如nums = [1, 2, 3]中缺失的第一个正数为nums.length + 1。将整数存储在哈希表(空间复杂度为O(N)不符合常数级额外空间)中,然后再[1, nums.length + 1]中寻找不存在哈希表的数。
思路:liweiwei1419
class Solution {
// 利用哈希表
public int firstMissingPositive(int[] nums) {
// [1, nums.length + 1]中一定有一个是最小缺失正数
HashMap<Integer, Integer> map = new HashMap<>(nums.length);
for (int i = 0; i < nums.length; i++) {
if (nums[i] > 0)
map.put(nums[i], i);
}
for (int i = 1; i <= nums.length; i++) {
if (!map.containsKey(i))
return i;
}
return nums.length + 1;
}
}
自定义哈希(f(nums[i]) = nums[i] - 1)
解:遍历nums,根据f(nums[i]) = nums[i] - 1,nums[i] - 1为新的坐标,如果0 <= nums[i] - 1 < nums.length,交换nums[i] 和 nums[f(nums[i])]。之后再顺序遍历数组,如果nums[i] != i + 1就是缺失的第一个正数。
-
转换规则定义:
- 对于数组
nums
中的每个元素nums[i]
,定义一个函数f(nums[i]) = nums[i] - 1
。 - 这个函数的作用是将
nums[i]
转换为一个新的索引nums[i] - 1
。
- 对于数组
-
交换操作:
- 如果
0 <= nums[i] - 1 < nums.length
,即新计算出的索引在数组范围内,则交换nums[i]
和nums[nums[i] - 1]
。这个操作旨在将每个元素移动到它应该在的位置。
- 如果
-
找缺失的正数:
- 在完成上述交换操作后,再次顺序遍历数组
nums
。 - 如果发现
nums[i] != i + 1
,则i + 1
即为缺失的第一个正数。这是因为正常情况下,第一个缺失的正数应该是从 1 开始递增的,而nums[i]
不等于i + 1
表示i + 1
缺失。
- 在完成上述交换操作后,再次顺序遍历数组
class Solution {
public int firstMissingPositive(int[] nums) {
// [1, nums.length + 1]中一定有一个是最小缺失正数
for (int i = 0; i < nums.length; i++) {
// 确保每次交换都能将 nums[i] 放到正确的位置上,直到无需交换为止。
while (nums[i] - 1 >= 0 && nums[i] - 1 < 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] != i + 1)
return i + 1;
}
return nums.length + 1;
}
private void swap(int[] nums, int a_idx, int b_idx) {
int tmp = nums[a_idx];
nums[a_idx] = nums[b_idx];
nums[b_idx] = tmp;
}
}