题目
给定一个未排序的整数数组,找出其中没有出现的最小的正整数。
示例 1:
输入: [1,2,0]
输出: 3
示例 2:
输入: [3,4,-1,1]
输出: 2
示例 3:
输入: [7,8,9,11,12]
输出: 1
说明:
你的算法的时间复杂度应为O(n),并且只能使用常数级别的空间。
解题思路—正负翻转:此题有严格的时间复杂度与空间复杂度的要求,想要符合这个要求并不容易,所以该题级别判为困难不是没有原因的!!!解决此题的突破点是要充分利用原来的数组,在原数组上修改。
下面以例子来解释思路:
- 数组 nums 为 [1,2,-1,-2,0,8,5] ,先从头到尾遍历一遍,判断数组中有没有1的存在。如果存在1,则继续下一步;如果不存在,则输出最小的正整数1。
- 因为题目中要求的是没有出现的最小的正整数,所以负数和0在数组中没有意义。数组长度为7,而数组最大值为8,代表前面肯定有元素缺失,所以大于数组长度的值也没有意义。现在将数组中所有 负数、0和大于数组长度的数 都置1。
- 现在nums变为 [1,2,1,1,1,1,5] ,正式开始判断数组中缺少的最小正整数。从头开始遍历,现在数组中有1,2,5,将num[0,1,4]中的数值都变为负数(从0开始),表明当前元素存在。即num为 [-1,-2,1,1,-1,1,5] ,数组中元素一旦变为负数就不再更改(所以重复的数比如1,num[0]只需要变1次。)这种做法不会改变数组原本的数,取值的时候只需要加一个abs就行。
- 从头遍历修改后的 [-1,-2,1,1,-1,1,5] ,返回第一个为正数的数组索引值+1即可(从0开始),也就是3。
- 如果遍历完还没有return,就说明当前数组无缺失,返回 nums.length+1 即可。
Java解题—正负翻转
class Solution {
public int firstMissingPositive(int[] nums) {
if(nums==null || nums.length==0) return 1;
// 判断数组中是否有1
int isone = 0;
for(int i=0;i<nums.length;i++){
if(nums[i]==1)
isone++;
}
if(isone==0)
return 1;
// 把所有 负数和0和超出数组长度的数 都置1
for(int i=0;i<nums.length;i++){
if(nums[i]<=0 || nums[i]>nums.length)
nums[i] = 1;
}
for(int i=0;i<nums.length;i++){
int n = Math.abs(nums[i]);
if(nums[n-1]>0)
nums[n-1] = -nums[n-1];
}
for(int i=0;i<nums.length;i++){
if(nums[i]>0)
return i+1;
}
return nums.length+1;
}
}