[力扣]41. 缺失的第一个正数

29 篇文章 0 订阅
23 篇文章 0 订阅

符合题目的AC代码

class Solution:
    def firstMissingPositive(self, nums: List[int]) -> int:
        n = len(nums)
        for i in range(n):
            while nums[i] != i + 1 and nums[i] > 0 and nums[i] < n and nums[i] != nums[nums[i] - 1]:
                #nums[i],nums[nums[i] - 1] = nums[nums[i] - 1],nums[i]
                t1,t2 =nums[i],nums[nums[i] - 1]
                nums[nums[i] - 1] = t1
                nums[i] = t2

        for i in range(n):
            if nums[i] != i + 1:
                return i + 1
        return n + 1

不符合题目的AC代码

class Solution:
    def firstMissingPositive(self, nums: List[int]) -> int:
        D = {}
        for it in nums:D[it] = 1
        i = 1
        while i in D.keys(): i += 1
        return i

分析

由于本题的时间复杂度要求为 O ( n ) O(n) O(n),并且元素的取值范围为整数范围,所以最容易想到的处理方法便是借助哈希表——借助哈希表对每一个出现的值进行标记,每个取值的哈希时间为 O ( 1 ) O(1) O(1),哈希的总复杂度为 O ( n ) O(n) O(n)。然后在从1开始在哈希表中找出第一个没有出现的整数,该遍历过程的期望时间复杂度为 O ( n / 2 ) O(n/2) O(n/2)。所以该过程的总时间复杂度为 O ( n ) O(n) O(n),符合题目要求。然而,题目对于算法的空间复杂度同样有着严格的要求—— O ( 1 ) O(1) O(1)的时间复杂度。
使用哈希表的空间复杂度是线性的,明显不符合题目的要求。

对于该题,使用哈希表多是一件美事,无奈哈希表的空间复杂度不达标,有什么优化的策略呢?

这里就要借助数据本身的一些特性了。
即借助数据本身的特殊性构建出一个特殊的哈希表,达到 O ( 1 ) O(1) O(1)的复杂度要求。

在这里插入图片描述
如图所示,我们可以将每个数放到它应在的位置,最终的结果我们用 O ( n ) O(n) O(n)的复杂度完成了对数值与数组下标的映射——即哈希。

需要注意的是,数组中数的取值可能为负数、也可能为很大的数。
对于这些数,我们可以不予理睬——因为数组长度只有n,所以缺失的第一个正数不可能大于n + 1。

我们是不是在用了 O ( n ) O(n) O(n)的时间复杂度对一个数组进行了排序呢?
是的。
按照常规的认知,对于一个数组进行排序,最有的时间复杂度也得是 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n),为什么这里可以实现 O ( n ) O(n) O(n)的排序呢?

那是因为我们借助了这个数组的特殊性——或者说是排序规则的特殊性——我们只对整数的有限范围内的数据进行排序,且排序时需要每个数不重复(否则该数会被忽略)。


题目链接
原创不易,感谢支持!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wingaso

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值