一.问题描述
Given an array containing n distinct numbers taken from 0, 1, 2, ..., n
, find the one that is missing from the array.
Example 1:
Input: [3,0,1] Output: 2
Example 2:
Input: [9,6,4,2,3,5,7,0,1] Output: 8
Note:
Your algorithm should run in linear runtime complexity. Could you implement it using only constant extra space complexity?
二.解题思路
题目意思就是从0,1,...n这n+1个数中挑n个出来组成一个数组,找出漏掉的那一个。
注意一下题目的note, 使用常量空间。
如果没要求常量空间那很简单,就是做个hashmap,把0~n+1全部map False, 然后哪一个数出现就将dict[i]=True,
最后哪一个是False就说明缺了。
但是如果要求常量空间那这些方法显然不行。
方法1: 如果一个数没少,那么0~n这n+1个数的和是 (n*n+1)/2,现在少了一个数,这个数可以通过(n*n+1)/2和nums数组的和相减得到。
时间复杂度O(N), 空间复杂度O(1)。
方法2:
可以用异或操作来寻找。
我们知道数组值是从0~n,同时数组索引是从0~n-1。如果我们每次迭代异或它的值和索引值。
这道题可以转化成,在一个长度为2n+1的数组中,有n个元素出现两次,找那一个落单的。
假设是缺了第i个值,我们会异或 xor0 xor 1 ..xor i xor i+1...xor n xor 0 xor 1 xor 2 ....xor i-1 xor i+1 ...xor n
然后我们知道任意一个数被异或2次为0,即A xor A=0。最后会变成 0 xor i,求出结果。
方法3:
交换 swap
只需要让每个nums[i]=i,那么最后那个nums[i]!=i 就是遗失的那个数,
迭代每一个nums[i]通过下列交换让索引和值相匹配,直到nums[i]=i时停止。
每进行一次交换,会使得索引nums[i]处的值与索引相等(匹配,即nums[nums[i]]=nums[i]),并不是nums[i]与i匹配,注意一下。
详细见代码。
nums[nums[i]],nums[i]=nums[i],nums[nums[i]]
时间复杂度: O(n*n),空间复杂度O(1).
更多leetcode算法题解法: 专栏 leetcode算法从零到结束
三.源码
1.求和相减
class Solution:
def missingNumber(self, nums: List[int]) -> int:
return int((len(nums))*(len(nums)+1)/2)-sum(nums)
def missingNumber(self, nums: List[int]) -> int:
xor = 0 ^ len(nums)
for i, v in enumerate(nums):
xor ^= i
xor ^= v
return xor
3.交换 想法来源于想法来源于:https://leetcode.com/problems/missing-number/discuss/432654/268-Missing-Number-Py-All-in-One-By-Talse 略改动
class Solution:
def missingNumber(self, nums: List[int]) -> int:
l = len(nums)
for i in range(l):
#swap until you get the right value in current position
while nums[i] != i and nums[i] < l:
# nums[i], nums[nums[i]] = nums[nums[i]], nums[i], will lead to list assignment out of range error
nums[nums[i]],nums[i]=nums[i],nums[nums[i]]
for i, v in enumerate(nums):
if i != v: return i
return l