思路:
1.每遍历一个元素就比较在1-n之间是否有元素缺失,暴力遍历;时间复杂度会很高
2.使用哈希表来记录每个元素的出现次数,需要用到额外的空间
3.使用原数组来代替哈希表的功能,首先知道对于长度为n的数组,要么就是1-n的元素全出现,对应位置为[0,n-1],那么答案为n+1,要么就在1-n中的元素缺失;首先对于小于0的元素变为n+1,再遍历一遍,将所有元素-1的绝对值对应的位置的元素变为负数(比如说我元素为2,那就把坐标1的元素变为负数),这样最后剩下的元素为正的位置处的元素要么就是n+1,要么该位置就是缺失的元素-1。
4.通过置换的方法,把每个出现在的1-n的元素放到对应的元素-1的位置上,那么最后遍历一次元素和他位置+1不匹配的那么位置+1就是缺失的元素。
原题链接:https://leetcode.cn/problems/first-missing-positive/?favorite=2ckc81c
1.题目如下:
给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。
请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。
示例 1:
输入:nums = [1,2,0]
输出:3
示例 2:
输入:nums = [3,4,-1,1]
输出:2
示例 3:
输入:nums = [7,8,9,11,12]
输出:1
提示:
1 <= nums.length <= 5 * 105
-231 <= nums[i] <= 231 - 1
2.代码如下:
class Solution {
public:
//思路一:用哈希表,但是空间复杂度为O(n)
//思路二:暴力搜索,从1到n依次检索数组中是否有该数字 时间复杂度O(n2)
//思路三:使用置换方法;
/*
对于所有元素,在1-n应该都有一个对应的位置,如果位置不是对应的,就交换元素;
最后遍历的时候,如果坐标位置上的元素不等于该坐标+1,就是该元素缺失
*/
int firstMissingPositive(vector<int>& nums) {
int n=nums.size();
for (int i=0;i<n;++i) {
//如果元素在1-n区间,那么就一定会有一个对应的位置,如果不在该位置,就交换
while (nums[i]>0 && nums[i]<=n && nums[nums[i]-1]!=nums[i]) {
swap(nums[nums[i]-1],nums[i]);
}
}
for (int i=0;i<n;++i) {
if (nums[i]!=i+1) {
return i+1;
}
}
return n+1;
}
//思路四:创建哈希表的替代品 可知,没有出现的数字只有可能在1到n+1中;
/*
遍历数组,同时对小于0的数设为n+1
对于大于0小于n的数,将元素对应的位置的元素设为负数
*/
/*
int firstMissingPositive(vector<int>& nums) {
int n = nums.size();
for (int& num: nums) {
if (num <= 0) {
num = n + 1;
}
}
for (int i = 0; i < n; ++i) {
int num = abs(nums[i]);
if (num <= n) {
// ∣x∣−1 位置的数添加一个负号
nums[num - 1] = -abs(nums[num - 1]);
}
}
for (int i = 0; i < n; ++i) {
//如果一个位置元素大于0,则返回i+1
if (nums[i] > 0) {
return i + 1;
}
}
return n + 1;
}
*/
};