136. 只出现一次的数字

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

func singleNumber(nums []int) int {
    var ans int32 = 0
    for i := 0; i < 32; i++ {
        var tmp int32 = 0
        for _, num := range nums {
            // 对于每一个数的每一个二进制位分别累加
            // 左移将需要计算的位置放到最右边,再按位与上1,目的是清空其他位的值
            tmp += (int32(num) >> i) & 1
        }
        // 由于存在一个元素仅出现一次,跟3取余后能得到目标元素的第i位上的值
        if tmp % 2 != 0 {
            ans |= 1 << i // 注意这里是利用1左移回去占位,并与ans按位加上
        }
    }
    
    return int(ans)
}

当然异或的方式也可以

func singleNumber(nums []int) int {
    v := 0
    for _, num := range nums {
        v = v ^ num
    }
    return v
}

说明:你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

137. 只出现一次的数字 II

137. 只出现一次的数字 II

给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。

假设对于数组 [4, 3, 3, 3, 2, 2, 2],将所有的数看作二进制即

0100
0011
0011
0011
0010
0010
0010

对于32位int,如果我们将每一个二进制位都加起来(相当于上方数组的每一列相加),我们最终会得到 0163, 由于其余的数都出现了三次,所以每一位都和3取余可以得到 0100, 即能得到4

func singleNumber(nums []int) int {
    var ans int32 = 0
    for i := 0; i < 32; i++ {
        var tmp int32 = 0
        for _, num := range nums {
            // 对于每一个数的每一个二进制位分别累加
            // 左移将需要计算的位置放到最右边,再按位与上1,目的是清空其他位的值
            tmp += (int32(num) >> i) & 1
        }
        // 由于存在一个元素仅出现一次,跟3取余后能得到目标元素的第i位上的值
        if tmp % 3 != 0 {
            ans |= 1 << i // 注意这里是利用1左移回去占位,并与ans按位加上
        }
    }
    
    return int(ans)
}

260. 只出现一次的数字 III

260. 只出现一次的数字 III

给定一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。你可以按 任意顺序 返回答案。

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

对于数字6和-6

原码
0000 0000 0000 0110
1000 0000 0000 0110

反码
0000 0000 0000 0110
1111 1111 1111 1001

补码
0000 0000 0000 0110
1111 1111 1111 1010

&后
0000 0000 0000 0010

可以看到 6 & -6 后,只保留了最末尾的1
func singleNumber(nums []int) []int {
    xorVal := 0
    for _, num := range nums {
        xorVal ^= num
    }

    // &之后只保留了最末尾的1
    val := xorVal & -xorVal
    n1, n2 := 0, 0
    for _, num := range nums {
        // 这里其实是判断num在val最末尾1上的位是不是也是1
        if num & val == 0 {
            n1 ^= num
        } else {
            n2 ^= num
        }
    }

    return []int{n1, n2}
}