持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第6天,点击查看活动详情
一、题目描述:
448. 找到所有数组中消失的数字 - 力扣(LeetCode)
给你一个含 n 个整数的数组 nums ,其中 nums[i] 在区间 [1, n] 内。请你找出所有在 [1, n] 范围内但没有出现在 nums 中的数字,并以数组的形式返回结果。
示例 1:
输入:nums = [4,3,2,7,8,2,3,1]
输出:[5,6]
示例 2:
输入:nums = [1,1]
输出:[2]
提示:
- n == nums.length
- 1 <= n <= 10^5
- 1 <= nums[i] <= n
进阶:你能在不使用额外空间且时间复杂度为 O(n) 的情况下解决这个问题吗? 你可以假定返回的数组不算在额外空间内。
二、思路分析:
首先写了一种内存消耗比较小但是比较耗时的解法:将nums先排序,然后令lost为前面丢失的和后面丢失的值,然后遍历一遍nums,如果nums[i + 1] > nums[i] + 1,就说明nums[i] + 1 ~ nums[i + 1] - 1这一段里的数都是丢失的,添加到lost里即可。这个方法要注意,首先要把nums最小的数之前的和最大的数之后的添加上
然后看了解答之后发现我的解法过于愚蠢了。在此贴个我觉得很妙的解法
官方解法,由于nums的数字都在[1, n]之间,想利用这一范围之外的数字,来表达「是否存在」的含义。
首先注意数组的范围是[1,n],但下标的范围是[0, n-1],所以我们将nums[i]对应数字i + 1. 遍历一下数组,如果遇见了xx,由于xx对应nums[x-1x−1],于是将nums[x-1x−1]加上n,这样,最后再看一遍nums,如果nums[i]在[1,n]之间,则说明i+1没有出现过 要注意的是,当我们遍历到某个位置时,其中的数可能已经被增加过,因此需要对n取模来还原出它本来的值。
三、AC 代码:
class Solution:
def findDisappearedNumbers(self, nums: List[int]) -> List[int]:
n = len(nums)
nums.sort()
lost = list(range(1, nums[0])) + list(range(nums[-1] + 1, n + 1))
for i in range(n-1):
if nums[i + 1] > nums[i] + 1:
lost = lost + list(range(nums[i]+1, nums[i + 1]))
return lost