这一题如果不要求时间复杂度O(n),空间复杂度O(1),那还是有很多种办法可以做的,不过既然加了这些限制,就必须考虑用什么算法来求解了。
我个人觉得,这一题主要是要想到,长度为n的数组,要找的数最大只可能是n+1,也就是要找的数会小于等于n。然后怎么判断这个数是n+1以内的数呢?通常做法我们是用一个flag数组,遍历一遍就知道哪个数是没有出现了,但是这里只允许O(1)的空间复杂度,所以可以采用在原地处理的方式,把这个区间内的数放到它应该在的位置。
比如如果有元素1,那么它应该被放到0的位置,如果有元素4,它应该被放到3的位置,如果有元素k,那它应该被放到k-1的位置。
#include<algorithm>
class Solution {
public:
int firstMissingPositive(vector<int>& nums) {
if(nums.size() == 0)
return 1;
int n = nums.size();//获取总长度,则要找的这个数肯定小于等于n+1
//接下来把数组在1到n范围内的数都摆放到应该在的位置上,如果后期检查这个位置上的数不是在这里的,那就证明这个数是要找的
for(int i = 0;i < n;)
{
if(nums[i]>=1 && nums[i] <= n)//这个数在范围内,它是否在他正确的位置上呢?
{
if(nums[i] != i+1 && nums[nums[i]-1] != nums[i])//不在正确位置上,那就把这个数换到它正确的位置上去(前提是那个数和这个不相等,不然就陷入死循环了)
{
swap(nums[nums[i]-1],nums[i]);//比如5,应该放到nums[4]那里去
continue;
}
}
++i;
}
for(int i = 0;i < n;++i)//检查每个位置上是不是正确的数
if(nums[i] != i+1)
return i+1;
return n+1;//如果最后没找到值与位置不匹配的数,证明正好就是前n个数在那里,所以返回n+1
}
};