> 文章列表 > 【算法】【数组与矩阵模块】求数组中从未出现的最小正整数(含拓展思路)

【算法】【数组与矩阵模块】求数组中从未出现的最小正整数(含拓展思路)

【算法】【数组与矩阵模块】求数组中从未出现的最小正整数(含拓展思路)

目录

  • 前言
  • 问题介绍
  • 解决方案
  • 代码编写
    • java语言版本
    • c语言版本
    • c++语言版本
  • 思考感悟
  • 写在最后

前言

当前所有算法都使用测试用例运行过,但是不保证100%的测试用例,如果存在问题务必联系批评指正~

在此感谢左大神让我对算法有了新的感悟认识!

问题介绍

原问题
给定数组arr,求数组中从未出现的最小正整数
如:arr = [-1,3,4,5]
结果为0
要求空间复杂度为O(1),时间复杂度O(n)

解决方案

原问题
1、申请两个变量l和r,作为arr的左右游标
2、遍历arr,如果arr[l] = l + 1,说明arr[l]在理想的位置,l++
3、否则如果 arr[l] <= l 或者arr[l] > r 或者 arr[arr[l] - 1] = arr[l](这个出现过的值已经在理想的位置上了),r–,arr[l] = arr[r]
4、如果不满足2和3,则说明arr[l]还在范围之中,只不过没有遍历到而已,将arr[l]放到应该去的地方
5、直到l=r,遍历结束,返回l+1即可

代码编写

java语言版本

原问题:
方法一:

  /*** 二轮测试:计算数组中未出现的最小正整数* @param arr* @return*/public static int getMissNumCp1(int[] arr) {if (arr == null || arr.length == 0) {return -1;}// 期望arr = [1,2,3,4,5,6...],l代表截止目前已经存在的范围[1,l],r代表截止目前,后面无论多么理想,范围最优[1...r]int l = 0, r = arr.length;while (l < r) {if (arr[l] == l+1) {// arr[l]在理想的位置l++;}else if (arr[l] <= l || arr[l] > r || arr[arr[l] - 1] == arr[l]) {// arr[l]不在期望的区间内,或者在期望区间内但是不在当前位置// 期望的范围-1,因为出现了期望之外的值或者有重复值r--;arr[l] = arr[r];}else{// 出现了期望的值,但是不在应该在的位置上CommonUtils.swap(arr, l, arr[l] - 1);}}return l + 1;}public static void main(String[] args) {System.out.println(getMissNumCp1(new int[]{-1,2,3,4}));}

c语言版本

正在学习中

c++语言版本

正在学习中

思考感悟

这道题如果不限制空间,用统计法瞬间就能解决。
这道题如果不限制时间,排个序再遍历一下瞬间就能解决。
但是。。。时间和空间都在最小的范围内解决这道题的办法,其实还是比较经得起推敲的
首先我们要真的理解r和l两个游标的含义,我们要求的是数组中从未出现过的正整数,关键词在于正整数,这跟l初始化为0是紧密关联的,可不是因为arr的起始坐标为0而设计的,l存在的意义就是为了遍历中验证在arr中l+1这个值出现过没有?
我们可以这么理解,理想情况下arr=[1,2,3,4,5,6,…],最小正整数如果存在,那么整个数组中小于正整数的数必须会存在,否则它就不是最小正整数了,并且最小正整数一定会存在于[1,2,3,4,5…arr.len]。那么现在遍历l,我们先判断是否是理想情况,如果是的那么l++,很好理解,当遇到不是理想的情况时,当前的值可能有几种情况呢?1、这个数应该在的坐标arr[l]-1超出了理想的范围,( (-∞, l)∪(r,+∞)),或者这个数已经在自己应该在的位置上了,重复,所以有这个条件 arr[l] <= l || arr[l] > r || arr[arr[l] - 1] == arr[l],这种情况下说明整个数组的候选者范围减小,因此当前值应该和arr[r]交换(这里因为当前值坑定不是最小值了,所以使用了直接覆盖的方式),之后r–。
2、这个数如果没有出界,说明了这个数还在[l…r]之间,只不过没有到它应该在的位置上,这个时候将这个数和它应该在的位置上的值进行一个交换(这里呼应了为什么要判断一下是否存在重复,否则这里会死循环)
这道题理解起来其实比较费劲,整个过程类似于遍历坐标,然后找这个坐标上的值是否应该在它应该在的位置上,如果不在的话是否在范围中,如果也不在,则整个范围就会减小,最小值不会超过r

写在最后

方案和代码仅提供学习和思考使用,切勿随意滥用!如有错误和不合理的地方,务必批评指正~
如果需要git源码可邮件给2260755767@qq.com
再次感谢左大神对我算法的指点迷津!