题目大意:给定一个没有排序的整数数组,找到第一个未出现的正数。
例:[1,2,0]结果为3。[3,4,1,-1]结果为2。
要求:算法必需是O(n)时间,并且是常量空间。
思路一:
1、利用hash表,遍历每一个元素,将其中大于0的值作为实际值和键值加入到hash中。
2、从键值为i=1开始逐次加1查找,当不能找到此键值的元素时,此时的i即为所求。
上述思路为刚开始没注意到常量空间时想到的,实现简洁,但需要新建hash表,耗费空间不为常数。
提交之后,leetcode上照样ac了,运行时间为4ms,代码如下:
class Solution {
public:
int firstMissingPositive(vector<int>& nums) {
unordered_map<int,int> hash;
for(int i=0;i<nums.size();++i)
{
if(nums[i]>0)
hash[nums[i]]=nums[i];
}
int j=1;
while(hash.find(j)!=hash.end())++j;
return j;
}
};
需要常量空间,因为考虑O(n)的要求,只能在原数组上进行交换操作,不然无法在常量空间中记录遍历的信息。
思路二:
1、对于数组的每一个元素,将其放到正确的位置上。即,a[0]=1,a[1]=2,a[2]=3...下面代码中的for循环执行过程实例:
对于[3,4,5,0,1];执行i=0时,第一次执行while循环满足判断条件,交换a[0]和a[2]得到[5,4,3,0,1];
第二次执行while循环满足判断条件,交换a[0]和a[5]得到[1,4,3,0,5]。这样就将a[0]位置上放置了正确的元素。
2、查找第一个元素值和位置不符合的位置,即为所求。
ac的代码如下,运行时间4ms:
class Solution {
public:
int firstMissingPositive(vector<int>& nums) {
for(int i=0;i<nums.size();++i)
while(nums[i]>0&&nums[i]<nums.size()&&nums[i]!=nums[nums[i]-1])
swap(nums[i],nums[nums[i]-1]);
int j=0;
while(j<nums.size()&&nums[j]==j+1)++j;
return j+1;
}
};