给你一个未排序的整数数组,请你找出其中没有出现的最小正整数。
示例 :[1,2,0] 输出 :3
[3,4,-1,1] 输出:2
[7,8,4,6] 输出:1
要求: 算法时间复杂度为O(n),并且不能使用常数级别的额外空间
解题思路:一个长度为n的数组,它缺失的最小正整数一定≤n+1,假设最极端的数组中存储的是123~n,那么缺失的也是n+1,
如果前面也有缺失那他一定小于n+1;
利用这个思想,我们可以对号入座,即将数字x(x要是小于数组长度的正整数)放在数组的x-1的位置上,
即最理想的状态是nums[0]放1,nums[1]放2。。。然后在去找哪个位置没有放对应的数,就可以找到哪个缺失的正整数
这里在第一次排序时候,只需要将数组中出现的1~n的数进行对号入座,其它数可以不移动,因为没有其对应的位置入座,
代码如下:
public class FirstMissingNum {
public static void main(String args[]){
//假定如下数组
int[] nums = {-1,1,3,33,3,543,61};
int k;//下面循环用于交换位置的中间变量
//遍历数组,目的就是将数组中的第i个位置存储(i+1)这个值,如果没有(i+1)这个值,就不移动
for(int i = 0;i<nums.length;i++) {
//将每个数字赋值给val进行判断
int val = nums[i];
//先排除小于0 的情况,因为小于0的数可以不移动,没有其对应的位置,不然下面会出bug
if(val<1) {
continue;
//剔除大于数组长度的元素,因为没有其对应的位置
//其次如果第i个位置就存放了i+1这个数,那么就不需要移动。
//其次如果第i个位置已经有了i,那么后面再出现i不能互相交换,不然会死循环
}else if(val<=nums.length&&val!=(i+1)&&nums[val-1]!=val) {
//这里可以理解为桶排序,就是将数组中的数字x存放到x-1的位置上
k = nums[i];
nums[i] = nums[k-1];
nums[k-1] = k;
//应为有两个数交换了位置,那么第i个位置的值需要重新判断,所以这里先自减1,后面在循环中在自增1,相当于没有变
i--;
}
}
boolean flag = true;
//循环判断数组下标对应的数是不是满足条件,如果不是,就找到了
for(int i = 0;i<nums.length;i++) {
if(nums[i]!=i+1) {
flag = false;
System.out.println("该数组缺失的最小正整数为"+(i+1));
break;
}
}
if(flag) {
//代码能执行到这,说明数组中存储的是1~n,那么缺失的就应该是数组长度+1
System.out.println("该数组缺失的最小正整数为"+(nums.length+1));
}
}
}