【数组】力扣645:错误的集合

集合 s 包含从 1 到 n 的整数。不幸的是,因为数据错误,导致集合里面某一个数字复制了成了集合里面的另外一个数字的值,导致集合丢失了一个数字并且有一个数字重复
给定一个数组 nums 代表了集合 S 发生错误后的结果。
请你找出重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。
示例1:

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

示例2:

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

可能用到的函数

  1. sum(iterable[, start]) 求和
    其中,中括号[]表示可省略的元素。
    iterable -- 可迭代对象,如:列表、元组、集合。
    start -- 指定相加的参数,如果没有设置这个值,默认为0。
    e.g.
    >>>sum([0,1,2]) 3
    >>> sum((2, 3, 4), 1) # 元组计算总和后再加 1 10
    >>> sum([0,1,2,3,4], 2) # 列表计算总和后再加 2 12
  2. list() 把元组换成列表

自以为是的错误答案:

class Solution:
    def findErrorNums(self, nums: List[int]) -> List[int]:
        for i in range(len(nums)):
            if nums[i+1] - nums[i] == 0:
                a = nums[i]
            elif nums[i+1] - nums[i] != 1:
                b = nums[i] + 1
        return [a, b]

编码也不对,if nums[i+1] - nums[i] == 0: 为什么不对呢??
而且也没有考虑一种特殊情况:如果丢失的数字是 1 或 n。

一行代码解决问题:

class Solution:
    def findErrorNums(self, nums: List[int]) -> List[int]:
        # 列表list从1开始计数,数组从0,所以列表范围是(1, len(num)+1)
        return [sum(nums) - sum(set(nums)), sum(list(range(1, len(nums) + 1))) - sum(set(nums))]

官方解答3种方法:

  • 排序
    将数组排序之后,比较每对相邻的元素,即可找到错误的集合。
    寻找重复的数字较为简单,如果相邻的两个元素相等,则该元素为重复的数字。
    寻找丢失的数字相对复杂,可能有以下两种情况:
    如果丢失的数字大于 1 且小于 n,则一定存在相邻的两个元素的差等于 2,这两个元素之间的值即为丢失的数字;
    如果丢失的数字是 1 或 n,则需要另外判断。
    为了寻找丢失的数字,需要在遍历已排序数组的同时记录上一个元素,然后计算当前元素与上一个元素的差。考虑到丢失的数字可能是 1,因此需要将上一个元素初始化为 0。
    当丢失的数字小于 n 时,通过计算当前元素与上一个元素的差,即可得到丢失的数字;
    如果nums[n-1] != n,则丢失的数字是 n。
    时间复杂度:O(nlogn),其中 n 是数组 nums 的长度。排序需要O(nlogn) 的时间,遍历数组找到错误的集合需要 O(n) 的时间,因此总时间复杂度是 O(nlogn)。
    空间复杂度:O(logn),其中 n 是数组 nums 的长度。排序需要 O(logn) 的空间。

  • 哈希表
    重复的数字在数组中出现 2 次,丢失的数字在数组中出现 0 次,其余的每个数字在数组中出现 1 次。因此可以使用哈希表记录每个元素在数组中出现的次数,然后遍历从 1 到 n 的每个数字,分别找到出现 2 次和出现 0 次的数字,即为重复的数字和丢失的数字。
    时间复杂度:O(n),其中 n 是数组 nums 的长度。需要遍历数组并填入哈希表,然后遍历从 1 到 n 的每个数寻找错误的集合。
    空间复杂度:O(n),其中 n 是数组 nums 的长度。需要创建大小为 O(n) 的哈希表。

  • 位运算
    使用位运算,可以达到 O(n) 的时间复杂度和 O(1) 的空间复杂度。
    重复的数字在数组中出现 2 次,丢失的数字在数组中出现 0 次,其余的每个数字在数组中出现 1 次。由此可见,重复的数字和丢失的数字的出现次数的奇偶性相同,且和其余的每个数字的出现次数的奇偶性不同。如果在数组的 n 个数字后面再添加从 1 到 n 的每个数字,得到 2n 个数字,则在 2n 个数字中,重复的数字出现 3 次,丢失的数字出现 1 次,其余的每个数字出现 2 次。根据出现次数的奇偶性,可以使用异或运算求解。

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/set-mismatch/solution/cuo-wu-de-ji-he-by-leetcode-solution-1ea4/

posted @   Vonos  阅读(43)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示