【Problem:41. 缺失的第一个正数】从哈希表到原地哈希优化
Problem:41. 缺失的第一个正数
题目描述
给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。
请你实现时间复杂度为 O ( n ) O(n) 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 <= nums.length <= 10^5-2^31 <= nums[i] <= 2^31 - 1
解法一:哈希表
若不考虑空间开销,第一时间想到的就是哈希表,将数组元素加入哈希表中,从 i = 1 开始遍历,当 i 在哈希表中不存在时,记录答案退出循环即可。
class Solution {
public:
int firstMissingPositive(vector<int>& nums) {
int n = nums.size();
unordered_set<int> st;
int ans = 0;
for(int i = 0;i < n;i++) {
st.emplace(nums[i]);
}
for(int i = 1;;i++) {
if(st.find(i) == st.end()) {
ans = i;
break;
}
}
return ans;
}
};
⏱️ 时间复杂度: O ( N ) O(N) O(N)
🏠 空间复杂度: O ( N ) O(N) O(N)
解法二:原地哈希
由于题目要求空间复杂度是常数级,考虑对数组 nums 进行原地操作,结合答案具有以下特点:
- 若数组
nums长度为n,则答案一定在[1,n+1]之间; - 若整个数组是连续的,那么答案就是
n+1; - 否则答案就是第一个缺失的数。
我们可以通过交换,尝试让数字 i 落在数组下标为 i-1 的位置上(例如:数字 1 放在 nums[0],数字 2 放在 nums[1])。
算法步骤:
- 遍历并放置: 遍历数组,如果当前的数
nums[i]是正数,且 n u m s [ i ] ≤ n nums[i] le n nums[i]≤n,并且它不在它应该在的位置上(即 n u m s [ i ] ≠ n u m s [ n u m s [ i ] − 1 ] nums[i] eq nums[nums[i]-1] nums[i]=nums[nums[i]−1]),就将它与其正确位置上的数进行交换。 - 查找缺失值: 再次遍历数组。第一个满足 n u m s [ i ] ≠ i + 1 nums[i] eq i + 1 nums[i]=i+1 的下标 i i i,对应的 i + 1 i + 1 i+1 就是我们要找的最小正整数。
- 边界情况: 如果数组遍历完都符合条件,说明
1到n全都在,返回n + 1(ans初始化为n+1)。
⚠️注意:
这里使用 while 循环是因为交换回来的新数可能仍然需要被交换到它正确的位置。
代码实现:
class Solution {
public:
int firstMissingPositive(vector<int>& nums) {
int n = nums.size();
int ans = n+1;
for(int i = 0;i < n;i++) {
while(nums[i] > 0 && nums[i] <= n && nums[i] != nums[nums[i] - 1]) {
swap(nums[i],nums[nums[i]-1]);
}
}
for(int i = 0;i < n;i++) {
if(nums[i] != i + 1) {
ans = i + 1;
break;
}
}
return ans;
}
};
⏱️ 时间复杂度: O ( N ) O(N) O(N)
🏠 空间复杂度: O ( 1 ) O(1) O(1)
❤️ 最后
新人up,如有不足还请
多多指正,欢迎交流!
如果内容对你有帮助的话,还请点赞支持一下喽🙏🙏
你的支持是我前进的最大动力!!
up正在更新力扣hot100的题目,有需要的朋友欢迎点赞、收藏加关注哦!








