LeetCode算法题268:缺失数字

这是一道简单题,但是做法很多,有一个算法还涉及到了数学知识,这里给大家分享一下。

题目描述如下:

给定一个包含 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

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值