首页 缺失数字
文章
取消

缺失数字

给定一个包含 0, 1, 2, ..., nn 个数的序列,找出 0 .. n 中没有出现在序列中的那个数。

示例 1:

1
2
输入: [3,0,1]
输出: 2

示例 2:

1
2
输入: [9,6,4,2,3,5,7,0,1]
输出: 8

说明: 你的算法应具有线性时间复杂度。你能否仅使用额外常数空间来实现?

异或法

只出现一次的数字: 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

如果我们补充一个完整的数组和原数组进行组合,那所求解的问题就变成了 只出现一次的数字

将少了一个数的数组与 0 到 n 之间完整的那个数组进行异或处理,因为相同的数字异或会变为了 0 ,那么全部数字异或后,剩下的就是少了的那个数字。

如图

代码实现

1
2
3
4
5
6
7
8
9
10
func missingNumber(_ nums: [Int]) -> Int {
        
    var res = nums.count
    for i in 0..<nums.count {

        res ^= nums[i]
        res ^= i
    }
    return res
}

求和法

思路

  • 求出 0 到 n 之间所有的数字之和
  • 遍历数组计算出原始数组中数字的累积和
  • 两和相减,差值就是丢失的那个数字

图解

代码实现

1
2
3
4
5
6
7
8
9
10
func missingNumber(_ nums: [Int]) -> Int {
    
    // 先求出0...n的总和
    var res = (1 + nums.count) * nums.count / 2
    for num in nums {

        res -= num
    }
    return res
}

二分法

将数组进行排序后,利用二分查找的方法来找到缺少的数字,注意搜索的范围为 0 到 n 。

  • 首先对数组进行排序
  • 用元素值和下标值之间做对比,如果元素值大于下标值,则说明缺失的数字在左边,此时将 right 赋为 mid ,反之则将 left 赋为 mid + 1 。

注:由于一开始进行了排序操作,因此使用二分法的性能是不如上面两种方法。

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
func missingNumber(_ nums: [Int]) -> Int {
        
    let res = nums.sorted(by: <)
    var left = 0
    var right = res.count
    while left < right {

        let mid = (left + right) / 2
        if mid < res[mid] {

            right = mid
        } else {

            left = mid + 1
        }
    }
    return left
}

源码地址

本文由作者按照 CC BY 4.0 进行授权

Alamofire 源码剖析

Moya框架浅析