巧用位运算快速计算出数值的反码

119 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第18天,点击查看活动详情

题目描述

每个非负整数 N 都有其二进制表示。例如, 5 可以被表示为二进制 "101"11 可以用二进制 "1011" 表示,依此类推。注意,除 N = 0 外,任何二进制表示中都不含前导零。

二进制的反码表示是将每个 1 改为 0 且每个 0 变为 1。例如,二进制数 "101" 的二进制反码为 "010"

给你一个十进制数 N,请你返回其二进制表示的反码所对应的十进制整数。

示例

输入: 5
输出: 2
解释: 5 的二进制表示为 "101",其二进制反码为 "010",也就是十进制中的 2
输入: 7
输出: 0
解释: 7 的二进制表示为 "111",其二进制反码为 "000",也就是十进制中的 0
输入: 10
输出: 5
解释: 10 的二进制表示为 "1010",其二进制反码为 "0101",也就是十进制中的 5

提示

  1. 0 <= N < 10^9

字符串转换

我们可以将目标值转换成二进制的字符串,然后从右往左遍历该字符串,判断其每一位的元素,如果当前位置元素为0,则我们需要在结果变量这边加上对应的值,具体步骤如下:

  1. 将目标值转换成二进制字符串
  2. 由于二进制是从右往左延伸的,所以我们需要从右往左遍历二进制字符串
  3. 定义一个count变量,表示当前二进制位置对应的值,初始值为1
  4. 当目标值当前的二进制位为0时,其反码为1,我们需要加上当前位置对应的值
  5. count左移一位
class Solution {
    public int bitwiseComplement(int n) {
        String binary = new StringBuilder(Integer.toBinaryString(n)).toString();
        int res = 0, count = 1;
        for(int i = binary.length() - 1; i >= 0; --i){
            if(binary.charAt(i) == '0'){
                res += count;
            }
            count <<= 1;
        }
        return res;
    }
}

异或

异或规则0⊕0=0,1⊕0=1,0⊕1=1,1⊕1=0(同为0,异为1),我们可以利用这个特性,先得到一个比目标值大,且全部位数都为1的数值,再将其与目标值进行异或运算,即可得到最终结果。

class Solution {
    public int bitwiseComplement(int n) {
        int res = 1;
        while(res < n){
            // 结果左移一位,再加上 1,保持其二进制均为 1 构成
            res = (res << 1) + 1;
        }

        return res ^ n;
    }
}