【2022-09-26每日一题】面试题 17.19. 消失的两个数字[Hard]

2022-09-26
2分钟阅读时长

2022-09-26每日一题:面试题 17.19. 消失的两个数字

难度:Hard

标签:位运算 、 数组 、 哈希表

给定一个数组,包含从 1 到 N 所有的整数,但其中缺了两个数字。你能在 O(N) 时间内只用 O(1) 的空间找到它们吗?

以任意顺序返回这两个数字均可。

示例 1:

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

示例 2:

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

提示:

  • nums.length <= 30000

方法一:位运算

详细思路过程见官方题解,这里只做个人刷题记录,方便后续查询阅读

func missingTwo(nums []int) []int {
    xorNum, n := 0, len(nums) + 2
    for _, num := range nums {
        xorNum ^= num
    }
    for i := 1; i <= n; i++ {
        xorNum ^= i
    }
    lsb := xorNum & -xorNum
    type1, type2 := 0, 0
    for _, num := range nums {
        if lsb & num > 0 {
            type1 ^= num
        } else {
            type2 ^= num
        }
    }
    for i := 1; i <= n; i++ {
       if lsb & i > 0 {
            type1 ^= i
        } else {
            type2 ^= i
        }
    }
    return []int{type1, type2}
}

复杂度分析

  • 时间复杂度:O(n),其中 n 是最大的整数。需要遍历的数字有 2n−2 个,共遍历两次。
  • 空间复杂度:O(1)。

方法二:数学

func missingTwo(nums []int) []int {
    n := len(nums) + 2
    cur := n * (n + 1) / 2  // 计算n个数的和
    for _, num := range nums {
        cur -= num // 最终得到两个缺失数的和
    }
    // 根据补全后数值各不相同可知,两者必不可能同时位于t的同一侧
    sum, t := cur, cur/2 
    cur = t * (t + 1) / 2 // 计算1...t范围内数的和
    for _, num := range nums {
        if num <= t {
            cur -= num  // 求解前面缺失的数
        }
    }
    return []int{cur, sum-cur}
}

复杂度分析

  • 时间复杂度:O(n)。
  • 空间复杂度:O(1)。

LeetCode题库地址