给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。
请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。
输入:nums = [1,2,0]
输出:3
输入:nums = [3,4,-1,1]
输出:2
输入:nums = [7,8,9,11,12]
输出:1
1 )一般思路
function firstMissingPositive(nums: number[]): number {
// 过滤掉非正整数
nums = nums.filter(item => item > 0);
// 正整数数组是为空
if (!nums.length) return 1;
// 升序,目的:方便从左到右取最小值arr[0]
nums.sort((a, b) => a - b);
// 如果第一个元素不为1,返回1
if (nums[0] !== 1) return 1;
// 从左边开始遍历,只要下一个元素和当前元素差值》1说明当前元素的下一个值(+1)
for (let i = 0, len = nums.length - 1; i < len; i++) {
if (nums[i + 1] - nums[i] > 1) {
return nums[i] + 1;
}
}
// 如果数组是连续的正整数【1,2,3,4,5,6】
return nums.pop() + 1;
}
2 )基于冒泡改造
function firstMissingPositive(nums: number[]): number {
nums = nums.filter(item => item > 0);
const n = nums.length;
let min: number;
// 实现选择排序,先拿到最小值,如果第一个元素不是1直接返回1,如果是1,就要比相邻元素差值
for (let i: number = 0; i < n; i++) {
min = nums[i];
for (let j: number = i + 1; j < n; j++) {
if (nums[j] < min) {
let c = min;
min = nums[j];
nums[j] = c;
}
}
nums[i] = min;
if (i > 0) {
if (nums[i] - nums[i - 1] > 1) return nums[i - 1] + 1;
} else {
if (min !== 1) return 1;
}
}
return nums.length ? nums.pop() + 1 : 1;
}
3 )查询表
function firstMissingPositive(nums: number[]): number {
const n: number = nums.length;
const { abs } = Math;
let i: number;
for (let i = 0; i < n; ++i) {
if (nums[i] <= 0) {
nums[i] = n + 1;
}
}
for (i = 0; i < n; ++i) {
let num = abs(nums[i]);
if (num <= n) {
nums[num - 1] = -abs(nums[num - 1]);
}
}
for (i = 0; i < n; ++i) {
if (nums[i] > 0) {
return i + 1;
}
}
return n + 1;
}
4 )置换法
function firstMissingPositive(nums: number[]): number {
const n = nums.length;
let i: number;
for (i = 0; i < n; ++i) {
while (nums[i] > 0 && nums[i] <= n && nums[nums[i] - 1] != nums[i]) {
[nums[nums[i] - 1], nums[i]] = [nums[i], nums[nums[i] - 1]]; // 交换
}
}
for (i = 0; i < n; ++i) {
if (nums[i] != i + 1) {
return i + 1;
}
}
return n + 1;
}