给定一个未排序的整数数组,找出其中没有出现的最小的正整数。
示例 1:
输入: [1,2,0]
输出: 3
示例 2:
输入: [3,4,-1,1]
输出: 2
示例 3:
输入: [7,8,9,11,12]
输出: 1
说明:
你的算法的时间复杂度应为O(n),并且只能使用常数级别的空间。
*/
/*
* 题目大意:找到一个未排序序列中的第一个缺失的正数。简而言之,就是看1在不在这个序列中,如果不在的话输出1;
* 否则看2在不在这个序列中,如果不在的话输出2;否则看3在不在这个序列中
思路:
本题的一个难点就在 要求O(n)时间复杂度 O(1)空间复杂度 不允许申请新的空间
1.先说说O(n)空间复杂度的解法 利用HashSet存放所有的数组元素 然后从1开始 找到第一个不在set里面的元素 就是最小值
2.O(1)空间复杂度的解法
nums[i]代表该数在数组中应该处于第i个位置 对应数组的索引就是i-1 也就是nums[i]-1
举个例子,假设有序列[4,2,6,1,-3],首先看第一个数4,它正确的位置应该是在序列的第4个位置(位置数从1开始,正确的位置是第一个位置放1,第二个位置放2,第三个位置放3……最后我们只要看哪个位置放的不是理想的数,
那么它就是第一个缺失的正数)。我们将4与第4个位置上的“1”进行交换,序列变成[1,2,6,4,-3];接着我们还是
看第一个数,现在变成了“1”,它的确在它正确的位置,好了,我们再看第二个数2,也在正确的位置。第三个数6,
本来应该放在第6个位置,可是该序列总共就5个位置,所以不移动;第四个数4在它的正确位置,不动;第五个数是负数,
不动。最后,从前往后看,发现在第三个位置本该出现的3没有出现,所有该序列缺失的第一个正数是3。
//时间复杂度应为O(n),并且只能使用常数级别的空间
public static int firstMissingPositive(int[] nums) {
int len=nums.length;
for (int i = 0; i < len; i++) {
//nums[i]代表该数在数组中应该处于第i个位置 对应数组的索引就是i-1 也就是nums[i]-1
//由于负数不考虑 所以nums[i]>0 而nums[i]如果大于数组长度 则也不用交换
while (nums[i]>0&&nums[i]<=len&&nums[i]!=nums[nums[i]-1]) {
swap(nums,i,nums[i]-1);
}
}
//操作完成之后 遍历 找到nums[i]第一个不等于i+1的点 结果就是i+1
for (int i = 0; i < len; i++) {
if (nums[i]!=i+1) {
return i+1;
}
}
//都符合要求了 说明数组的值是 1~nums.length 则返回
return len+1;
}
private static void swap(int[] nums, int i, int j) {
int temp=nums[i];
nums[i]=nums[j];
nums[j]=temp;
}