一.問題描述
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