这道题,我的思路大致如下:
首先对数组进行排序,设置一个计数为i,记录已经出现的正整数数目,依次遍历排序后的数组,判断大于0的元素是否等于i,若不等于可以判断为缺少的最小正整数就是i;要考虑的特殊情况是有重复数字出现和最后一位元素的判断。若与前一位数字相同,则继续下一次遍历,i不递增,特殊的如果最后一位是重复的,直接返回i;若判断到最后一位,返回i+1。如果不是特殊情况,i递增,继续遍历。
class Solution {
public:
int firstMissingPositive(vector<int>& nums) {
sort(nums.begin(),nums.end());
if(nums.size()==0)return 1;
if(nums.size()==1){
if(nums[0]!=1)return 1;
else return 2;
}
int i=1;
for(int j=0;j<nums.size();j++)
{
if(nums[j]>0)
{
if(nums[j]!=i)
{
if((nums[j]<i)&&j!=nums.size()-1)continue; //和前一位重复,且不是最后一位
else return i;
}
else
{
if(j==nums.size()-1)return i+1; //当遍历到最后一位
if(nums[j]!=nums[j-1]) i++;
}
}
}
}
};
这种方法容易想到,但是总是有一些没考虑的情况,要通过测试数据添加。在网上看到了其他人的做法,还是太笨呀,在此也记录下来。
虽然不能再另外开辟非常数级的额外空间,但是可以在输入数组上就地进行swap操作。
思路:交换数组元素,使得数组中第i位存放数值(i+1)。最后遍历数组,寻找第一个不符合此要求的元素,返回其下标。整个过程需要遍历两次数组,复杂度为O(n)。
下图以题目中给出的第二个例子为例,讲解操作过程。
n个元素的数组,里面的数都是0~n-1范围内的,求数组中重复的某一个元素,没有返回-1, 要求时间性能O(n) 空间性能O(1)。
实现代码如下:
public class Solution {
public int firstMissingPositive(int[] nums) {
if(nums.length == 0)
return 1;
//第i位存放i+1的数值
for(int i = 0; i < nums.length;i++){
if(nums[i] > 0){//nums[i]为正数,放在i+1位置
//如果交换的数据还是大于0且<i+1,则放在合适的位置,且数据不相等,避免死循环
//这个while是关键,其他都是没有难度的
while(nums[i] > 0 && nums[i] < i+1 && nums[i] != nums[nums[i] -1]){
int temp = nums[nums[i]-1];//交换数据
nums[nums[i]-1] = nums[i];
nums[i] = temp;
}
}
}
//循环寻找不符合要求的数据,返回
for(int i = 0; i < nums.length;i++){
if(nums[i] != i+1){
return i+1;
}
}
//如果都符合要求,则返回长度+1的值
return nums.length + 1;
}
}