题目:给定一个正整数,输出它的补数。补数是对该数的二进制表示取反。
注意:
- 给定的整数保证在32位带符号整数的范围内。
- 你可以假定二进制数不包含前导零位
示例 1:
输入: 5 输出: 2 解释: 5的二进制表示为101(没有前导零位),其补数为010。所以你需要输出2。
示例 2:
输入: 1 输出: 0 解释: 1的二进制表示为1(没有前导零位),其补数为0。所以你需要输出0。
第一想到的比较简单的方法就是求这个书的二进制然后取反,本文介绍另一种方法,利用位移和异或运算来实现。因为异或运算的原理就是相同为0,相异为1,可以看到示例1中5这个数字的二进制与2这个数的二进制的每一位做异或运算都是1,因为本身它们每一位都是不同的(2是由5的二进制每一位取反而得)。同理,从5的二进制最后一位开始,对每一位和1进行异或运算就得到了2,过程如下:
1 0 1 数字5
^1 ^1 ^1 每一位与1做异或运算
0 1 0 结果:数字2
代码如下:
public static int findComplement(int num) {
int result = 0, i = 0;
while (num > 0) {
result += ((num % 2) ^ 1) << i++; // 要将数字左移回相应的位置上
num >>= 1; // 处理完最后一位后要右移一位
}
return result;
}
如代码所示,循环从最后一位开始跟1做异或运算,然后每次往左移一位,直到这个数字的最高位被处理完就可以结束了。