leetCode第448题 找到所有数组中消失的数字
给你一个含 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 <= 105
1 <= nums[i] <= n
进阶:你能在不使用额外空间且时间复杂度为 O(n) 的情况下解决这个问题吗? 你可以假定返回的数组不算在额外空间内。
在python中判断一个元素在列表中直接用 元素名 in 列表名就能判断
dis = [] for i in range(1,len(nums)+1): if i not in nums: dis.append(i)
但这种写法每次判断一个元素就要遍历整个列表,势必会导致超时
而且与题中进阶的要求也不符合,就算记录成hash map然后检索,也是占用了而外的空间
要想时间复杂度为O(n),且不占用而外的空间,那么我们只能利用数组本身,这很难让人找到灵感。
以[4,3,2,7,8,2,3,1]为例,我们要把数字和下标联系起来,但是不能使用hash map。
-------------------------------
要在一遍循环内找到消失的数,就得利用题中给的条件:所有的数都在1-n之间,我们需要做一个变换,使得他的值不在1-n,这样通过一个范围的比较就能发现哪些数不对。
-----------------------------
数组本身只能告诉我们两个信息,一个是下标,另一个是数值,这势必要将数值和下标联系起来。在python中,下标是从0开始,我们将第一个数字4为例,将4-1得到下标3,我们将列表的3对应的值做一个变换,使得它不在1-n,不妨直接添一个负号(也可以直接加上n,使范围不在1-n),得到的是-7,对第二个元素3,使下标2应的值变为负数,得到-2,如果已经是负数,就不必更改。
------------------------------
这样[4,3,2,7,8,2,3,1],就变成了[-4,-3,-2,-7,8,2,-3,1],这样我们可以看到下标4,5对应的值还是整数。因为python的下标从0开始,所以对应的是缺失了5和6。
-------------------------------
因为数据中缺失了5,6所以我们无法操作下标4,5,反过来,下标对应的值没被更改,就是因为缺失了操作下标的数。
## python3
class Solution:
def findDisappearedNumbers(self, nums: [int]) -> [int]:
for i in range(len(nums)):
index = abs(nums[i])-1
if nums[index] > 0:
nums[index] = -nums[index]
dis = []
for i in range(len(nums)):
if nums[i] > 0:
dis.append(i+1)
return dis
也可以用+n的操作,使数值不在1-n这个范围,进一步判断
## python3
class Solution:
def findDisappearedNumbers(self, nums: [int]) -> [int]:
n = len(nums)
for i in range(n):
index = (nums[i]-1)%n
nums[index] += n
dis = []
for i in range(n):
if(nums[i] <= n):
dis.append(i+1)
return dis