LeetCode - 448. Find All Numbers Disappeared in an Array

本文介绍了一种算法问题的两种高效解决方案:寻找给定数组中缺失的数字,且这些数字位于特定范围内。第一种方法利用数组操作标记出现过的数字,而第二种方法则采用集合运算找出差异。

题目链接:448. Find All Numbers Disappeared in an Array


题意:给你一个整数数组,数组的值都是1≤a[i]≤nn是数组的长度),有些数字会出现两次,但是有的数字只会出现一次。
找到所有在[1, n]这个数组中,但是不在给的数组中的数。(也就是符合1≤a[i]≤n,但是没有出现在给定数组中的数)
你能不用额外的存储空间并在O(n)时间内解决问题吗?你可以认为返回的结果数组并不占用额外的空间。


解析:这个题的意思非常好理解,但是如何在不占用额外的存储空间并且在O(n)时间内解决问题,是个需要思考的点,另外如果不注意的话,直接两层嵌套循环是会超时的。


先上一种比较有意思的解法:
这个解法有两个有趣的点,第一个是给数组前面加一个[0],这也是为第二点服务的;第二点是通过遍历数组中所有的值,并找到其对应的数组下标(题目设定,数的大小在数组长度内),将对应下标的值设置为负数,最后按照下标遍历,只要对应下标上的数值不为负数,说明这个下标的值不在数组中。
这里解释一下为什么要用绝对值abs()函数,因为有些数字会出现两次,如果不使用绝对值abs()做的话,会让出现了两次的数,转化为正数,结果就会出错了。
这个效率还ok,超过50%+。

def findDisappearedNumbers(self, nums):
        nums = [0] + nums
        for i in range(len(nums)):
            index = abs(nums[i])
            nums[index] = -abs(nums[index])

        return [i for i in range(len(nums)) if nums[i] > 0]

再上一种最优解法,不仅效率高(超过95%的通过者),而且非常的简洁:
这种解法就是直接把数组转化为set集合,并将数组的长度n中包含的所有值转化为另一个set,二者求差,并转化为list返回。
真的是非常非常吊的解法啊。

class Solution(object):
    def findDisappearedNumbers(self, nums):
        return list(set(range(1, len(nums) + 1)) - set(nums))

最后的最后,写到这里的时候突然有点突发奇想,如果我们在第一种解法中,直接nums转化为set在进行处理,那就不需要使用abs()函数处理了,说不定一定程度上可以提高效率,这个留给读者去尝试吧。

为了避免读者踩坑,这里贴上超时的代码,请注意看清楚,这是没有通过的超时了的代码
这段代码后半部分if x not in nums]本质上还是使用循环判断是否存在的,也就是说这个代码是双重嵌套循环,这个解法死在了倒数第5组测试样例上,所以我个人估计题目的样例最后5组都是数量量比较大的(保守估计10万级(10的5次方)及以上)。

#超时代码
class Solution(object):
    def findDisappearedNumbers(self, nums):
        return [x for x in range(1, len(nums)+1) if x not in nums]

以上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值