题目如下:
解题思路:
直接想法是用 排序 或 哈希表 ,但是题目要求时间复杂度为O(n),空间复杂度为O(1),因此这两种方法都不满足要求。
数组大小为 n 时,负数 和 大于等于n+2 的数都不会是缺失的第一个整数,即缺失的第一个整数的范围只会是 [1 ~ n+1] 。掌握这个核心思想后,对数组做三次遍历:
- 1)、将不可能为返回结果的0和负数,置为同样不可能为返回结果的数字,比如len+2;
- 2)、将有可能为返回结果的数(1~len),绝对值减1之后作为下标,置对应位置的数字为负数;
- 3)、最后一趟,找到第一个还是正数的位置pos,返回pos+1;如果没找到,那就返回len+1;
class Solution {
public:
int firstMissingPositive(vector<int>& nums) {
int pos = 0;
int len = nums.size();
//第一次遍历,处理0和负数
while(pos < len)
{
if(nums[pos] <= 0)
nums[pos] = len + 2;
pos++;
}
//第二次遍历,处理绝对值在1 - len之间的数字(因为处理过程会再次出现负数)
pos = 0;
while(pos < len)
{
if(nums[pos] <= len && nums[pos]+len >= 0)
//nums[pos]的绝对值减1之后作为下标,置对应位置的数字为负数
//因为对应位置的值可能是1-len之间的数字,因此将其置为负数
//其值在后续循环中继续作为绝对值在1-len之间的数字进行处理
nums[abs(nums[pos]) - 1] = -abs(nums[abs(nums[pos]) - 1]);
pos++;
}
//第三次遍历,找到第一个还是正数的位置pos,返回pos+1
pos = 0;
while(pos < len)
{
if(nums[pos] > 0)
return pos + 1;
pos++;
}
return len + 1;
}
};