Leetcode算法——41、寻找缺失的正数

76 篇文章 1 订阅

给定一个乱序的整数数组,找到最小的缺失的正整数。

示例:

Example 1:
Input: [1,2,0]
Output: 3

Example 2:
Input: [3,4,-1,1]
Output: 2

Example 3:
Input: [7,8,9,11,12]
Output: 1

思路

1、标记法

如果 nums 的长度为 l,则结果肯定是在 1 ~ (l+1) 中的某个数。这是因为当 nums 包含了 1~l 的所有值时, 算法结果最大,为 l+1。

因此只需要定义一个额外的数组 list2,长度为 l,来标记对应的索引是否出现过正数即可。

具体步骤:

  • 定义一个额外的数组 list2,长度为 l,元素都为 0
  • 遍历 nums,每遇到一个小于等于 l 的元素值 a,便将 list2 中的a索引标记为1
  • 遍历 list2, 找到第一个为 0 的位置,这个位置即为最小的缺失正整数

此方法的算法复杂度为 O(l),空间复杂度为 O(l)。

2、改进版

标记法需要额外创建数组,可以对其进行改进,不再额外创建一个新数组,而是将 nums 当做新数组。

注意:

  • 由于 nums 之前便有数据,因此在修改 nums 值时,需要将原来的值保存下来,即与当前指针的值互换位置。
  • 将 nums 值修改为多少,可以保证这个索引出现过呢?不能是任何一个固定的数字,否则如果 nums 恰好为这个数字,则不知道应该不应该被标记。可以是一个固定的字符串,这样就可以与原有的数字们区分开来。

python实现

def firstMissingPositive(nums):
    """
    :type nums: List[int]
    :rtype: int
    如果 nums 的长度为 l,则结果肯定是在 1 ~ (l+1) 中的某个数,
    因为当 nums 包含了 1~l 的所有值时, 算法结果最大,为 l+1。
    因此只需要定义一个额外的数组 list2,长度为 l,元素都为 0。
    遍历 nums,每遇到一个小于等于 l 的元素值 a,便将 list2 中的a索引标记为1。
    之后再遍历一遍 list2, 找到第一个为 0 的位置,这个位置即为最小的缺失正整数。
    """
    
    l = len(nums)
    if l == 0:
        return 1
    
    list2 = [0] * l
    for i in nums:
        if i > 0 and i <= l:
            list2[i-1] = 1
    
    for i in range(l):
        if list2[i] == 0:
            return i+1
    return l+1

def firstMissingPositive2(nums):
    """
    :type nums: List[int]
    :rtype: int
    改进版。
    """
    
    l = len(nums)
    if l == 0:
        return 1
    
    for i in range(l):
        tmp = nums[i]
        while tmp != 'a' and tmp > 0 and tmp <= l:
            nums[tmp-1], tmp = 'a', nums[tmp-1]
    
    for i in range(l):
        if nums[i] != 'a':
            return i+1
    return l+1

if '__main__' == __name__:
    nums = [3,4,-1,1]
    print(firstMissingPositive2(nums))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值