这是一道简单题,但是做法很多,有一个算法还涉及到了数学知识,这里给大家分享一下。
题目描述如下:
给定一个包含 0, 1, 2, ..., n 中 n 个数的序列,找出 0 .. n 中没有出现在序列中的那个数。
示例 1:
输入: [3,0,1]
输出: 2
示例 2:
输入: [9,6,4,2,3,5,7,0,1]
输出: 8
说明:
你的算法应具有线性时间复杂度。你能否仅使用额外常数空间来实现?
第一种解法——排序:
第一种解法是排序法,这种方法很简单,先利用Python内置的排序函数对题给数组进行排序,然后让排序后的数组中的每个数与它们所在的下标进行对比,如果不匹配则返回下标,如果遍历到最后没有发现缺失数字,说明缺失的是最后一个数(如[0,1,2,3],缺失的是数字4),返回最后一个数。
Python3:
class Solution(object):
def missingNumber(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
nums.sort()
for i in range(len(nums)):
if i!=nums[i]:
return i
return len(nums)
这种方法相当于这道题的暴力解法,所以比较耗时。
第二种解法——哈希:
这种解法实际上是利用了集合的方法,Python中集合查找的时间复杂度是O(1),所以比较节省时间。
Python3:
class Solution(object):
def missingNumber(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
nums_set = set(nums)
n = len(nums)+1
for i in range(0,n):
if i not in nums_set:
return i
第三种解法——位运算(异或):
高等数学好长时间没碰了,这种方法也是看了官方题解后才明白,异或的运算规则是:两个相同的数字异或结果为0,两个不相同的数字异或结果为1。
这道题所用的思路是:一个数字经过两次完全相同的异或运算后结果为它本身。例如:
1^1^1=(1^1)^1=0^1=1.(^为Python中的异或运算)
我们知道数组中有n个数,我们可以用0到n的异或值与数组中的所有数字异或一次,因为未缺失的数字出现了两次,所以异或结果为0,缺失数字只出现了一次,所以最终结算结果为缺失的数字。例如:
nums=[0,1,2,4]
missing = 0^1^2^3^4^0^1^2^4=(0^0)^(1^1)^(2^2)^(4^4)^3=0^0^0^0^3=3.
因为一次循环便完成了所有的异或运算,所以时间复杂度为O(n);只使用了一个变量来存储缺失数字,所以空间复杂度为O(n)。
Python3:
class Solution:
def missingNumber(self, nums):
missing = len(nums)
for i, num in enumerate(nums):
missing ^= i ^ num
return missing
第四种解法——数学:
这种方法是利用高斯求和公式算出0到n的和,然后在减去数组中所有数字的和,便可得出缺失数字。例如:
nums=[0,1,2,4]
0到n为:0,1,2,3,4
0到n的和为:0+1+2+3+4=10
nums数组和为:7
缺失数字为:3
高斯求和公式:n*(n+1)/2
Python3:
class Solution(object):
def missingNumber(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
n = len(nums)
s1 = n*(n+1)/2
s2 = sum(nums)
return s1 - s2