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

BM53-缺失的第一个正整数

题目

给定一个无重复元素的整数数组nums,请你找出其中没有出现的最小的正整数。

进阶: 空间复杂度 O(1),时间复杂度 O(n)。

数据范围:

−2^31≤nums[i]≤2^31−1。

0≤len(nums)≤5∗10^5。

示例1

输入:[1,0,2]

返回值:3

示例2

输入:[-2,3,4,1,5]

返回值:2

示例3

输入:[4,5,6,8,9]

返回值:1


思路1:哈希表

n个长度的数组,没有重复,则如果数组填满了1~n,那么缺失n+1,如果数组填不满1~n,那么缺失的就是1~n中的数字。对于这种快速查询某个元素是否出现过的问题,还是可以使用哈希表快速判断某个数字是否出现过。

具体做法:

  • step 1:构建一个哈希表,用于记录数组中出现的数字。
  • step 2:从1开始,遍历到n,查询哈希表中是否有这个数字,如果没有,说明它就是数组缺失的第一个正整数,即找到。
  • step 3:如果遍历到最后都在哈希表中出现过了,那缺失的就是n+1。

代码1

import java.util.*;

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * @param nums int整型一维数组 
     * @return int整型
     */
    public int minNumberDisappeared (int[] nums) {
        int n = nums.length;
        HashMap<Integer, Integer> mp = new HashMap<Integer, Integer>();
        //哈希表记录数组中出现的每个数字
        for(int i = 0; i < n; i++) {
            mp.put(nums[i], 1);
        }
        int res = 1;
        //从1开始找到哈希表中第一个没有出现的正整数
        while(mp.containsKey(res)) {
            res++;
        }
        return res;
    }
}
  • 时间复杂度:O(n),第一次遍历数组,为O(n),第二次最坏从1遍历到n,为O(n)。
  • 空间复杂度:O(n),哈希表记录n个不重复的元素,长度为n。

思路2:原地哈希

前面提到了数组要么缺失1~n中的某个数字,要么缺失n+1,而数组正好有下标0~n−1可以对应数字1~n,因此只要数字1~n中某个数字出现,就可以将对应下标的值做一个标记,最后没有被标记的下标就是缺失的值。

具体做法:

  • step 1:可以先遍历数组将所有的负数都修改成n+1。
  • step 2:然后再遍历数组,每当遇到一个元素绝对值不超过n时,则表示这个元素是1~n中出现的元素,我们可以将这个数值对应的下标里的元素改成负数,相当于每个出现过的正整数,我们把与它值相等的下标都指向一个负数,这就是类似哈希表的实现原理的操作。
  • step 3:最后遍历数组的时候碰到的第一个非负数,它的下标就是没有出现的第一个正整数,因为它在之前的过程中没有被修改,说明它这个下标对应的正整数没有出现过。

代码2

import java.util.*;

public class Solution {
    public int minNumberDisappeared (int[] nums) {
        int n = nums.length;
        //遍历数组
        for (int i = 0; i < n; i++) {
            //负数全部记为n+1
            if (nums[i] <= 0) {
                nums[i] = n + 1;
            }
        }
        for (int i = 0; i < n; i++) {
            //对于1-n中的数字
            if (Math.abs(nums[i]) <= n) {
                //这个数字的下标标记为负数
                nums[Math.abs(nums[i]) - 1] = -1 * Math.abs(nums[Math.abs(nums[i]) - 1]);
            }
        }           
        for (int i = 0; i < n; i++) {
            //找到第一个元素不为负数的下标
            if (nums[i] > 0) {
                return i + 1;
            }
        }
        return n + 1;
    }
}
  • 时间复杂度:O(n),多次遍历数组,都是单层循环。
  • 空间复杂度:O(1),原地哈希,以索引为指向,没有额外空间。

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

相关文章:

  • 【6. 激光雷达接入ROS】
  • Java集合框架与ArrayList、LinkedList的区别
  • 操作系统——操作系统逻辑结构
  • Hbase数据库完全分布式搭建以及java中操作Hbase
  • Opencv识别车牌
  • 多级缓存建设方案
  • PHP图片上传代码怎么写和代码的用发
  • vue3表单输入绑定
  • DDD系列:三、Repository模式
  • C++项目中打破循环依赖的锁链:实用方法大全
  • 【Java校招面试】基础知识(二)——Spring Framework AOP
  • java stream 实践篇
  • day1_内存区域
  • 枚举法计算24点游戏
  • C++Primer第五版【阅读笔记】
  • LeetCode 560. 和为 K 的子数组
  • kettle不同数据源的字段不一致的合并后插入数据库
  • 如何使用快速排序算法对整数数组进行就地排序?
  • 从4k到42k,软件测试工程师的涨薪史,给我看哭了
  • 我的医学预测模型评价步骤(仅供参考)
  • SmartEngine流程引擎之Custom模式
  • ApplicationContextAware接口
  • ETL工具 - Kettle 输入输出算子介绍
  • MyBatisPlus代码生成器使用
  • Linux Ansible角色介绍
  • Python使用AI animegan2-pytorch制作属于你的漫画头像/风景图片
  • 3.3 泰勒公式例题分析
  • c++ 11标准模板(STL) std::vector (三)
  • 同时使用注解和 xml 的方式引用 dubbo 服务产生的异常问题排查实战
  • 抓马,互联网惊现AI鬼城:上万个AI发帖聊天,互相嗨聊,人类被禁言