41. 缺失的第一个正数
41. 缺失的第一个正数
题目
Given an unsorted integer array nums
, return the smallest missing positive integer.
You must implement an algorithm that runs in O(n)
time and uses O(1)
auxiliary space.
Example 1:
Input: nums = [1,2,0]
Output: 3
Explanation: The numbers in the range [1,2] are all in the array.
Example 2:
Input: nums = [3,4,-1,1]
Output: 2
Explanation: 1 is in the array but 2 is missing.
Example 3:
Input: nums = [7,8,9,11,12]
Output: 1
Explanation: The smallest positive integer 1 is missing.
Constraints:
1 <= nums.length <= 10^5
-2^31 <= nums[i] <= 2^31 - 1
题目大意
给你一个未排序的整数数组 nums
,请你找出其中没有出现的最小的正整数。
请你实现时间复杂度为 O(n)
并且只使用常数级别额外空间的解决方案。
解题思路
思路一:哈希表
为了减少时间复杂度,可以把 input
数组都装到 map
中,然后 i
循环从 1
开始,依次比对 map
中是否存在 i
,只要不存在 i
就立即返回结果,即所求。但是这种方法的空间复杂度为 O(n)
,不满足题意。
复杂度分析
- 时间复杂度:
O(n)
,需要遍历数组。 - 空间复杂度:
O(n)
,需要一个大小为n
的哈希表存储数据。
思路二:原地哈希
原地哈希的意思是利用数组的索引来存储元素的存在性。具体来说,将每个值 x
放到数组的索引 x-1
处(即 nums[x-1]
),如果 x
的值在 [1, n]
范围内。这样做的前提是,数组中只有正整数。
遍历数组:
- 首先遍历数组,将每个有效的正整数放到正确的位置(即将
x
放到nums[x-1]
)。 - 对于每个值
x
,如果1 ≤ x ≤ n
,并且nums[x-1]
不是x
,则交换nums[i]
和nums[x-1]
,直到nums[i]
在正确的位置。
- 首先遍历数组,将每个有效的正整数放到正确的位置(即将
第二次遍历:
- 再次遍历数组,找到第一个位置
i
,使得nums[i]
不等于i + 1
,那么i + 1
就是缺失的正整数。
- 再次遍历数组,找到第一个位置
边界情况:
- 如果所有位置都满足
nums[i] = i + 1
,那么缺失的第一个正整数就是n + 1
。
- 如果所有位置都满足
复杂度分析
- 时间复杂度:
O(n)
,数组只遍历了两次。 - 空间复杂度:
O(1)
,只使用了常量级别的额外空间。
代码
/**
* @param {number[]} nums
* @return {number}
*/
var firstMissingPositive = function (nums) {
let map = new Map();
for (let i of nums) {
map.set(i, true);
}
let i = 1;
while (true) {
if (map.has(i)) i++;
else return i;
}
};
/**
* @param {number[]} nums
* @return {number}
*/
var firstMissingPositive = function (nums) {
const n = nums.length;
// 1. 将每个数放到对应的位置
for (let i = 0; i < n; i++) {
while (nums[i] > 0 && nums[i] <= n && nums[nums[i] - 1] !== nums[i]) {
// 交换 nums[i] 和 nums[nums[i] - 1]
const temp = nums[i];
nums[i] = nums[temp - 1];
nums[temp - 1] = temp;
}
}
// 2. 查找第一个缺失的正整数
for (let i = 0; i < n; i++) {
if (nums[i] !== i + 1) {
return i + 1; // 找到第一个缺失的正整数
}
}
return n + 1; // 如果 1 到 n 的正整数都在
};
相关题目
题号 | 标题 | 题解 | 标签 | 难度 | 力扣 |
---|---|---|---|---|---|
268 | 丢失的数字 | [✓] | 位运算 数组 哈希表 3+ | 🟢 | 🀄️ 🔗 |
287 | 寻找重复数 | [✓] | 位运算 数组 双指针 1+ | 🟠 | 🀄️ 🔗 |
448 | 找到所有数组中消失的数字 | 数组 哈希表 | 🟢 | 🀄️ 🔗 | |
765 | 情侣牵手 | 贪心 深度优先搜索 广度优先搜索 2+ | 🔴 | 🀄️ 🔗 | |
2336 | 无限集中的最小数字 | 设计 哈希表 有序集合 1+ | 🟠 | 🀄️ 🔗 | |
2554 | 从一个范围内选择最多整数 I | 贪心 数组 哈希表 2+ | 🟠 | 🀄️ 🔗 | |
2557 | 从一个范围内选择最多整数 II 🔒 | 贪心 数组 二分查找 1+ | 🟠 | 🀄️ 🔗 | |
2598 | 执行操作后的最大 MEX | 贪心 数组 哈希表 1+ | 🟠 | 🀄️ 🔗 | |
2996 | 大于等于顺序前缀和的最小缺失整数 | 数组 哈希表 排序 | 🟢 | 🀄️ 🔗 |