只出现一次的数字 III

这个还是有点难搞,许久不曾写算法了,还是有点慢了,持续了半个小时左右,并且使用了goland调式


package main

func singleNumber(nums []int) []int {
    if len(nums) == 0 {
        return []int{}
    }
    var mid int
    for _, v := range nums {
        mid ^= v
    }
    // 获取非0的第一位
    singleNum := mid & (^mid + 1)
    if singleNum == 0 {
        return []int{mid}
    }
    // 分成两组
    var r1, r2 int
    for _, v := range nums {
        if singleNum&v != 0 {
            r1 ^= v
        } else {
            r2 ^= v
        }
    }
    return []int{r1, r2}
}

思路

验证只出现一次的两个数字,首先还是使用异或的方法,先获取唯一的数,此时的这个数是两个目标数的异或,因为其他数都出现了两次,这个也很好理解是吧。
接着就是怎么把这些数分开的问题了,方法也很简单,使用上一步得出的结果,从低位到高位,找到第一个非0的位(先叫它非0位数),这意味着什么,这意味着原始数字可以在非0位数下,分成两组,巧妙,巧妙,大家细细品,看看是不是这样。
最后,对每组数进行分别异或,就可以得出来那两个只出现一次的数了。

中间有个小点,我觉得是值得拿出来说说的,就是如何获取非0位数,这个获取的方法有很多。我可以想到的有两种

  • 遍历 这个需要注意边界
  • 计算 这个就是让我很欣喜若狂的点singleNum := mid & (^mid + 1)

显然,在计算方式下,可以直接获取到我们的非0位数

你可能感兴趣的:(只出现一次的数字 III)