缺失的第一个正数

DESC:

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

进阶:你可以实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案吗?

示例 1:

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

示例 2:

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

示例 3:

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

提示:

    0 <= nums.length <= 300
    -231 <= nums[i] <= 231 - 1

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/first-missing-positive
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

CODE1:

JAVA:

class Solution {
    public int firstMissingPositive(int[] nums) {
        int n = nums.length;
        for (int i=0; i<n; i++) {
            if (nums[i]<=0) { //重点,注意包含等于号
                nums[i] = n+1;
            }
        }
        for (int i=0; i<n; i++) {
            int val = Math.abs(nums[i]); //重点,注意取绝对值
            if (val <= n) {
                nums[val-1] = -Math.abs(nums[val-1]); //重点,注意取绝对值,防止同一位置重复打标
            }
        }
        for (int i=0; i<n; i++) {
            if (nums[i]>0) {
                return i+1;
            }
        }
        return n+1;
    }
}

Python

class Solution:
    def firstMissingPositive(self, nums: List[int]) -> int:
        if not nums or len(nums) == 0:
            return 1
        n = len(nums)
        res = n+1
        for i in range(n):
            if nums[i]<=0:
                nums[i] = res
        for i in range(n):
            val = abs(nums[i])
            if val <= n:
                nums[val-1] = -1*abs(nums[val-1])
        for i in range(n):
            if nums[i] > 0:
                return i+1
        return res

NOTES:

  1. 打标,数组长度为n,结果肯定在[1,n+1]之间,将小于等于0的数都转换为n+1,此时数组区间是>=1,方便后面打标;
  2. 遍历数组,针对小于等于n的元素,在其本该属于的索引位置进行打标,转换为负数,如x=3,将index=2的位置元素的绝对值转为负数,标记3这个位置元素存在,但要注意取绝对值转为负数,防止这个位置被打多次,负正轮换;结束后,数组中元素本该在的位置都标记上了负数。
  3. 遍历数组,查找第一个不为负的位置,即表示该位置没有对应的元素打标,即为缺失值。每次遍历都是O(n)的时间复杂度。

CODE2:

JAVA:

class Solution {
    public int firstMissingPositive(int[] nums) {
        int n = nums.length;
        for (int i=0; i<n; i++) {
            while (nums[i]>0 && nums[i]<=n && nums[nums[i]-1] != nums[i]) {
                int temp = nums[nums[i]-1];
                nums[nums[i]-1] = nums[i];
                nums[i] = temp;
            }
        }
        for (int i=0; i<n; i++) {
            if (i+1!=nums[i]) {
                return i+1;
            }
        }
        return n+1;
    }
}

NOTES:

  1. 递归交换,遍历数组元素,将[1,n]间的元素放在其对应的位置,与其该存在的位置进行交换,但要避免相等重复交换死循环。如[2,3,1],i=0时,x=2,2和3互换后[3,2,1], x=3,仍然可继续互换为[1,2,3];直到不需要互换或x不在区间内
  2. 最后遍历数组,判断对应位置的元素知否为正确值,不是,则该位置为缺失的正数。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值