LeetCode第41题 缺失的正整数 难

该博客介绍了LeetCode第41题的解题思路和Java实现,题目要求找到未排序整数数组中缺失的最小正整数。通过排序和对号入座的方法,在O(n)的时间复杂度内找到答案。例如,对于输入数组[1,2,0],输出为3;对于[3,4,-1,1],输出为2;对于[7,8,4,6],输出为1。" 80400090,5760399,统计学习方法:感知机模型与学习算法解析,"['机器学习', '统计学习', '模型算法']
摘要由CSDN通过智能技术生成

给你一个未排序的整数数组,请你找出其中没有出现的最小正整数。
示例 :[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));
   }
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值