leetcode41-缺失的第一个正数

原题

给你一个未排序的整数数组,请你找出其中没有出现的最小的正整数。

示例 1:

输入: [1,2,0] 输出: 3

示例 2:

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

示例 3:

输入: [7,8,9,11,12] 输出: 1

提示:

你的算法的时间复杂度应为O(n),并且只能使用常数级别的额外空间。

解法

该题解同步发于leetcode:Java:比官方题解少一次循环

思想

见代码部分

代码

首先这道题有一个隐含条件:如果数组的大小为n,则缺失的第一个正数一定小于或等于n+1(取值最大的情况是数组中的数从1开始连续)

如果不限制常数级别的额外空间,可以使用bitmap的思想去做,如下:

class Solution {
    public int firstMissingPositive(int[] nums) {
        int n = nums.length;
        //下标对应出现的数-1
        int[] exist = new int[n+1];
        for(int i:nums){
            if(i<=0 || i > n) continue;
            exist[i-1] = 1;
        }
        for(int i = 0;i<n+1;i++){
            if(exist[i]==0) return i+1;
        }
        return 0;
    }
}

但是限制了常数级别的额外空间,可以思考一种替换bitmap的原地解法:

既然要原地,肯定需要在原数组上判断当前下标代表的正数是否出现,但又不能修改它的值,因为遍历的时候会用到,可以想到通过修改它的符号来判断。相较于新建一个数组作为bitmap去重的区别是,存在不存在不通过1或0标识,而是通过正负号标识(负号标识出现过,正号标识没出现)

但是数组中存在一些数原来就是负号的,可以先遍历一次让它们都变成正数,0也要变成一个正数,否则无法通过改变符号识别该下标代表的元素是否出现。但变成哪个正数值得考量,否则再次遍历有可能把他们当作数组中原有的数处理,那么就可以把它们设为n+1,因为n+1大于数组的长度,不会映射到数组中的位,可以不进行处理:

class Solution {
    public int firstMissingPositive(int[] nums) {
        int n = nums.length;
        //先将原来的负数的数置为 `n+1`
        for(int i = 0; i < nums.length ; i++){
            if(nums[i]<=0 ) {
                nums[i] = n+1;
            }
        }
        for(int i = 0; i < nums.length ; i++){
            int num = Math.abs(nums[i]);
            //绝对值大于数组长度的不处理
            if(num<=n && nums[num-1]>0) 
                nums[num-1] = -nums[num-1];
        }
        for(int i = 0;i<n;i++){
            if(nums[i]>0) return i+1;
        }
        return n+1;
    }
}

成功将官方题解的O(4N)优化成O(3N)~~~

原创文章,作者:彭晨涛,如若转载,请注明出处:https://www.codetool.top/article/leetcode41-%e7%bc%ba%e5%a4%b1%e7%9a%84%e7%ac%ac%e4%b8%80%e4%b8%aa%e6%ad%a3%e6%95%b0/

(0)
彭晨涛彭晨涛管理者
上一篇 2020年5月10日
下一篇 2020年5月11日

相关推荐

  • leetcode108-将有序数组转换为二叉搜索树

    原题 将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。 本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。 示例: 给定有序数…

    算法 2020年1月18日
    090
  • leetcode350-两个数组的交集II

    原题 给定两个数组,编写一个函数来计算它们的交集。 输入: nums1 = [1,2,2,1], nums2 = [2,2] 输出: [2,2] 示例2: 输入: nums1 = …

    算法 2019年12月23日
    0510
  • leetcode7-整数反转

    原题 给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。 示例1: 输入: 123 输出: 321 示例2: 输入: -123 输出: -321 示例3: 输…

    算法 2020年2月26日
    0120
  • leetcode435-无重叠区间

    原题 给定一个区间的集合,找到需要移除区间的最小数量,使剩余区间互不重叠。 注意: 可以认为区间的终点总是大于它的起点。 区间 [1,2] 和 [2,3] 的边界相互“接触”,但没…

    算法 2020年2月18日
    02440
  • 蓝桥杯试题-大小写转换

    原题 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述   输入一个字符串,将大写字符变成小写、小写变成大写,然后输出 输入格式 acbAB 输出格式 ACBab …

    算法 2020年2月29日
    080
  • leetcode387-字符串中的第一个唯一字符

    原题 给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。 案例: s = "leetcode" 返回 0. s = "loveleetcode"…

    算法 2019年12月22日
    0130
  • leetcode724-寻找数组的中心索引

    原题 给定一个整数类型的数组nums,请编写一个能够返回数组“中心索引”的方法。 我们是这样定义数组中心索引的:数组中心索引的左侧所有元素相加的和等于右侧所有元素相加的和。 如果数…

    算法 2019年11月13日
    0150
  • leetcode295-数据流的中位数

    原题 中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。 例如, [2,3,4] 的中位数是 3 [2,3] 的中位数是 (2 + 3) / 2 = 2.…

    算法 2020年2月12日
    0140
  • leetcode35-搜索插入位置

    原题 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 你可以假设数组中无重复元素。 示例 1: 输入: […

    算法 2020年3月2日
    0130
  • leetcode1103-分糖果II

    原题 排排坐,分糖果。 我们买了一些糖果 candies,打算把它们分给排好队的 n = num_people 个小朋友。 给第一个小朋友 1 颗糖果,第二个小朋友 2 颗,依此类…

    算法 2020年3月5日
    0140

发表回复

登录后才能评论