当前位置: 首页 > article >正文

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

目录

  • 前言
  • 问题介绍
  • 解决方案
  • 代码编写
    • 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
再次感谢左大神对我算法的指点迷津!


http://www.kler.cn/news/10637.html

相关文章:

  • FFMPEG: [ API ] >打开/关闭一个输入文件
  • Shiro概述
  • 9.1 相关分析
  • 定点乘法器优化---华为杯
  • Python求矩阵的特征值和广义特征值
  • 认识C++《共、枚、指1》
  • 什么是雪花算法?啥原理?
  • GORM 基础 -- Associations
  • 这7种常见的JavaScript错误,你知道吗?
  • 规模化敏捷框架:Scrum@Scale
  • 他98年的,我真的玩不过他...
  • 请我为详细讲解C11的新增原子操作
  • Oracle-主备切换问题(BUG-31747989)
  • 论文阅读 - ANEMONE: Graph Anomaly Detection with Multi-Scale Contrastive Learning
  • 大数据 | 实验一:大数据系统基本实验 | MapReduce 初级编程
  • JAVA经典之递归测试01-----JAVA入门基础教程
  • #详细介绍!!! 造成死锁的原因以及解决方案!
  • L2-042 老板的作息表(极短代码)
  • JavaScript【六】JavaScript中的字符串(String)
  • python+vue 在线考试系统的设计与实现
  • Quartz框架详解分析
  • 技术创业者必读:从验证想法到技术产品商业化的全方位解析
  • 算法训练Day29:491.递增子序列, 46.全排列 ,47.全排列 II
  • selenium自动化测试面试题【含答案】
  • 关于“复活节Easter”知识,你了解多少?
  • SadTalker项目上手教程
  • yolov8训练自己的数据集
  • 数据库系列之MySQL线程ID和操作系统线程ID对应关系
  • 雪花算法ID冲突问题与解决方案
  • 如何从 PowerPoint 导出高分辨率(高 dpi)幻灯片