日新刷题 - 476. 数字的补数

140 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第18天,点击查看活动详情

一、题目描述:

476. 数字的补数 - 力扣(LeetCode)

对整数的二进制表示取反(0110)后,再转换为十进制表示,可以得到这个整数的补数。

例如,整数 5 的二进制表示是 "101" ,取反后得到 "010" ,再转回十进制表示得到补数 2 。 给你一个整数 num ,输出它的补数。

 

示例 1:

输入:num = 5
输出:2
解释:5 的二进制表示为 101(没有前导零位),其补数为 010。所以你需要输出 2 。

示例 2:

输入:num = 1
输出:0
解释:1 的二进制表示为 1(没有前导零位),其补数为 0。所以你需要输出 0 。

 

提示:

  • 1 <= num < 2^31

二、思路分析:

作为 num 的补数 res,他们因为 每一位都是不一样的,那么相加起来,每一位必然都是 1。

比如二进制 101 + 010 ,结果就是 111,

可以观察得出, 数和补数之和 sum,必然是 全部是1,并且1的个数 和他们本身的位数相等,而 sum加1一定是 2 的倍数。

于是我们让 i 不停 乘以 2, 直到刚好 大于 num 即可。此时 i 的二进制是 1000 , 那么减去 1 就是 111,也就是上述的结果和。

i 永远是 2的倍数。 减1 就得到 数和补数之和

这个时候我们减去 num 就得到补数了

三、AC 代码:

class Solution {
    func findComplement(_ num: Int) -> Int {
        var i = 1
        while i <= num {
            i = i << 1
        }
        return i-1-num
    }
}

四、参考:

【zljhero】【C语言】 数字的补数:利用栈保存二进制位,取反计算 - 数字的补数 - 力扣(LeetCode)

Math.clz32(num)获取前导0的个数 - 数字的补数 - 力扣(LeetCode)

位运算 利用右移运算将给定的num最高位1之后的所有位置为1 再做异或运算 - 数字的补数 - 力扣(LeetCode)