Leetcode_hot100_41.缺失的第一个正数

题目要求

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

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

示例 1:
输入:nums = [1,2,0]
输出:3
解释:范围 [1,2] 中的数字都在数组中。

示例 2:
输入:nums = [3,4,-1,1]
输出:2
解释:1 在数组中,但 2 没有。

示例 3:
输入:nums = [7,8,9,11,12]
输出:1
解释:最小的正数 1 没有出现。

交换位置

把数组中的每个数放到它应该在的位置上,例如把 1 放到下标为 0 的位置,把 2 放到下标为 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
class Solution {
public int firstMissingPositive(int[] nums) {
int n = nums.length;

for (int i = 0; i < n; i++) {
// 将 nums[i] 放到正确的位置上,直到 nums[i] 不在范围 [1,n] 内或者 nums[i] 已经在正确的位置上
// 注意:这里使用 while 循环而不是 if,因为交换后 nums[i] 可能仍然需要继续交换
// 之所以是 nums[nums[i] - 1] != nums[i],而不是 nums[nums[i] - 1] != nums[nums[i] - 1],是为了避免死循环
while (1 <= nums[i] && nums[i] <= n && nums[nums[i] - 1] != nums[i]) {
int temp = nums[nums[i] - 1];
nums[nums[i] - 1] = nums[i];
nums[i] = temp;
}
}

for (int i = 0; i < n; i++) {
if (nums[i] != i + 1) {
return i + 1;
}
}

return n + 1;
}
}
  • 时间复杂度:O(n)。每个元素最多被交换两次。
  • 空间复杂度:O(1)。只使用了常数级别的额外空间。