Hot100 - 缺失的第一个正数

最佳思路:
此问题可以通过将数组元素交换到对应位置来实现。每个正整数 x
应该放置在索引 x-1
的位置。通过多次交换,我们可以确保每个正数都尽量放到其正确的位置。
时间复杂度:
该算法的时间复杂度为 O(n),因为每个元素最多只会被交换两次,遍历数组一次即可。
思路解析:
-
交换过程:我们遍历数组,对于每个元素
nums[i]
,如果它是一个有效的正数并且它的目标位置nums[i] - 1
上的值不是nums[i]
,就交换这两个元素。这样,数组中的每个正整数都将尽可能放到它应该在的位置。 -
第二次遍历:在交换完成后,再遍历一次数组,检查第
i
个位置的值是否是i + 1
。如果不是,那么i + 1
就是缺失的第一个正整数。 -
特殊情况:如果数组中的所有正整数都出现在正确的位置,那么缺失的第一个正整数就是数组的长度
len + 1
。
代码实现:
class Solution {
public int firstMissingPositive(int[] nums) {
int len = nums.length;
// 第一次遍历:交换数组元素到正确的位置
for (int i = 0; i < nums.length; i++) {
while (nums[i] <= len && nums[i] > 0 && 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;
}
}
// 如果所有正数都在正确的位置,返回 len + 1
return len + 1;
}
// 交换函数:交换数组中两个位置的元素
private void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
思路总结:
- 关键点:通过交换,将每个正整数放置到其对应的位置(
nums[i]
应该放在nums[i] - 1
位置)。之后,我们只需一次遍历来检查哪个位置没有按要求填充,返回对应的缺失值。 - 优点:这种方法不需要额外的空间,利用原数组完成操作,时间复杂度为 O(n),空间复杂度为 O(1)。