题目描述
给你一个未排序的整数数组 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 没有出现。
思路&js代码
1、标记(哈希)
- 我们将数组中所有小于等于 0 的数修改为 N+1;
- 我们遍历数组中的每一个数 x,它可能已经被打了标记,因此原本对应的数为 ∣x∣,其中 ∣∣ 为绝对值符号。如果 ∣x∣∈[1,N],那么我们给数组中的第 ∣x∣−1 个位置的数添加一个负号。注意如果它已经有负号,不需要重复添加;
- 在遍历完成之后,如果数组中的每一个数都是负数,那么答案是 N+1,否则答案是第一个正数的位置加 1。
var firstMissingPositive = function (nums) {
const len = nums.length
for (let i = 0; i < len; i++) {
if (nums[i] <= 0) {
nums[i] = len + 1
}
}
for (let i = 0; i < len; i++) {
const num = Math.abs(nums[i])
if (num <= len) {
nums[num - 1] = - Math.abs(nums[num - 1])
}
}
for (let i = 0; i < len; i++) {
if (nums[i] > 0) return i + 1
}
return len + 1
};2、置换
var firstMissingPositive = function(nums) {
const n = nums.length;
for (let i = 0; i < n; i++) {
// 如果当前学生的学号在 [1,n] 中,但(真身)没有坐在正确的座位上
while (1 <= nums[i] && nums[i] <= n && nums[i] !== nums[nums[i] - 1]) {
// 那么就交换 nums[i] 和 nums[j],其中 j 是 i 的学号
const j = nums[i] - 1; // 减一是因为数组下标从 0 开始
[nums[i], nums[j]] = [nums[j], nums[i]];
}
}
// 找第一个学号与座位编号不匹配的学生
for (let i = 0; i < n; i++) {
if (nums[i] !== i + 1) {
return i + 1;
}
}
// 所有学生都坐在正确的座位上
return n + 1;
};