leetcode 448. 找到所有数组中消失的数字

给定一个范围在  1 ≤ a[i] ≤ n ( n = 数组大小 ) 的 整型数组,数组中的元素一些出现了两次,另一些只出现一次。

找到所有在 [1, n] 范围之间没有出现在数组中的数字。

您能在不使用额外空间且时间复杂度为O(n)的情况下完成这个任务吗? 你可以假定返回的数组不算在额外空间内。


示例:

输入:
[4,3,2,7,8,2,3,1]

输出:
[5,6]

解法一:

class Solution(object):
    def findDisappearedNumbers(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        maxN = len(nums)
        if maxN == 0:
            return []
        disappearedNumbers = [1 for i in range(maxN)]
        for num in nums:
            disappearedNumbers[num-1] = 0
        result = []
        for i in range(maxN):
            if disappearedNumbers[i] != 0:
                result.append(i+1)
        return result

判断数字是否出现可以让我们很自然的想到用哈希表来记录,哈希表的读写速度为O(1),但是需要额外的内存O(n)来保存哈希表。这道题中因为数字是1到n,所以可以用数组下标的方式来模拟哈希表,下标即键,为数字减1。一开始我们获取数组长度n,然后创建一个长度为n,所有值都为1的列表来模拟哈希。随后遍历原nums数组,当一个numbe出现时,将哈希表中的值标为0。最后我们只需要遍历这个创建的数组,当遍历元素为非0时,将下标加1(即真实的数字)插入到result列表中。

该方法时间复杂度为O(n),空间复杂度为O(1)

解法二:

class Solution(object):
    def findDisappearedNumbers(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        maxN = len(nums)
        if maxN == 0:
            return []
        disappearedNumbers = [i+1 for i in range(maxN)]
        for num in nums:
            disappearedNumbers[num-1] = 0
        for i in range(maxN-1, -1, -1):
            if disappearedNumbers[i] == 0:
                disappearedNumbers.pop(i)
        return disappearedNumbers

解法二为解法一的改进版,不需要再用额外的空间创建新数组,而是在原来的disappearedNumbers上操作。修改了该数组的生成条件,假设n为3,那么解法1生成的列表为[1,1,1],而解法二生成的列表为[1,2,3]。最后我们只需要把所有的0元素pop出去,就得到了题目要求的答案。注意到我们这里需要从后往前遍历,不然pop就会出现下标问题。

该方法空间复杂度为O(1),但是时间复杂度为O(n^2),因为删除数组元组会涉及到后序元素的前移,需要O(n)的额外时间

解法三:

class Solution(object):
    def findDisappearedNumbers(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        
        # Iterate over each of the elements in the original array
        for i in range(len(nums)):
            
            # Treat the value as the new index
            new_index = abs(nums[i]) - 1
            
            # Check the magnitude of value at this new index
            # If the magnitude is positive, make it negative 
            # thus indicating that the number nums[i] has 
            # appeared or has been visited.
            if nums[new_index] > 0:
                nums[new_index] *= -1
        
        # Response array that would contain the missing numbers
        result = []    
        
        # Iterate over the numbers from 1 to N and add all those
        # that have positive magnitude in the array 
        for i in range(1, len(nums) + 1):
            if nums[i - 1] > 0:
                result.append(i)
                
        return result   

这个官方解法比较巧妙,还是利用数组的下标在原数组上进行操作,在遍历时,如数字3,则去检查index = 2 (3-1) 的元素是否为负,如果为非负就把它标。利用这种方式,可以用负数表示这个下标已经出现过,即下标对应的下标+1的数字已经出现过。最后返回所有元素为正的下标+1值就为未出现的数列。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值