[leetcode]First Missing Positive

来源:互联网 发布:淘宝营销活动是什么 编辑:程序博客网 时间:2024/06/07 06:23

原题连接https://leetcode.com/problems/first-missing-positive/.

如果数组是有序的话,那么显然可以在o(n)时间要求和常数空间要求内完成。但如果是乱序的,对数组排序至少需要o(nlogn)的时间,不可取。但如果可以在o(n)时间内使得数组的第k个位置,如果k+1是数组的一个元素,那么将k+1存放在数组的第k个位置上,即nums[k-=k+1。那么显然遍历nums,第一次出现nums[i-1]!=i的i即为所求。那么如何在o(n)时间内完成这样的调整呢?考虑如下:

1)nums[k]==k+1,即元素k在第k个位置,那么考察下一个位置,k=k+1;

2)nums[k]!=k+1,令j = nums[k],如果1<=j&&j<=nums.size(),即nums[k]存放的数j应该是第j个位置存放的数,那么将j,k位置的值互换,使得第j个位置的数为j。此时重新考察k位置。一种特殊情况是j位置上的数值已经是j了,那么久不需要互换了,直接考察下一个位置。

3)k从0开始直到最后一个位置。

如何证明以上恰好能达到目的呢?

从两种情况下考虑:

1)如果k+1不在数组的第k个位置,例如在第i个位置。如果在之前的某个位置k'发生过2)的k‘与i位置的上的数互换,那么互换后nums[k']=k+1,由2)在之后的重新考察位置k',可使得k+1放置到第k个位置上;如果没有发生过2)的位置互换过i位置的k+1,那么当考察到i时,可以使得k+1放置到第k个位置。

2)如果k+1在第k个位置,显然。

代码如下:

class Solution {
public:
int firstMissingPositive(vector<int>& nums) {
int t = 0;
int i = 0;
while(t<nums.size())
{
if(nums[t]!=t+1)
{
int j = nums[t];
if(1<=j&&j<=nums.size()&&nums[j-1]!=j)
{
nums[t]=nums[j-1];
nums[j-1]=j;
}
else
{
++t;
}
}
else
++t;
}
for(int i=0;i<nums.size();++i)
{
if(nums[i]!=i+1)
{
return i+1;
}
}
return nums.size()+1;
}
};

时间复杂度o(n),空间辅助度o(1)。

0 0
原创粉丝点击