力扣476(java)-数字的补数(简单)
题目:
对整数的二进制表示取反(0 变 1 ,1 变 0)后,再转换为十进制表示,可以得到这个整数的补数。
例如,整数 5 的二进制表示是 "101" ,取反后得到 "010" ,再转回十进制表示得到补数 2 。
给你一个整数 num ,输出它的补数。
示例 1:
输入:num = 5
输出:2
解释:5 的二进制表示为 101(没有前导零位),其补数为 010。所以你需要输出 2 。
示例 2:
输入:num = 1
输出:0
解释:1 的二进制表示为 1(没有前导零位),其补数为 0。所以你需要输出 0 。
提示:
- 1 <= num < 231
注意:本题与 1009 https://leetcode-cn.com/problems/complement-of-base-10-integer/ 相同
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/number-complement
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路:
找到给定数字num的二进制中最高位的1,将最高位的1所在位置以及比它低的位置全变为1,再与原数字进行异或运算即可得到答案。
1.【找到最高位的1】:从低位到高位开始找,每找到一个1,就把它变为0,直至num = 0时,当前的1就是最高位上的1;
2.【变1】:将最高位的1左移1位,再减去1,就可以得到最高位的1所在位置以及比它低的位置全变为1;
3.【与原数异或】
例如:9,二进制为:00..1001(32位)
第一次找到的1就是00..0001,把它变成0后的数字就变成了00..1000,然后找到第二个1就是00..1000,把它变成0后数字就变成了00..0000,故要找的最高位的1就是00..1000,然后把这个数字左移一位变成00..10000,再减去1得00..01111,然后再与00..1001进行异或运算得到的00..00110,即为6。
2个经典位运算:
-x :表示所有位置取反加1;
&:按位与,两个都是 1 的时候结果为1,否则结果为0;
x & (-x):保留二进制下最后出现的1的位置,其余位置置0;例如上面的第二个1(00..1000)
x & (x -1):清除二进制下最后出现1的位置的数字,其余位置保持不变;例如将00..1000变为00..0000以此来判断是否为最高位上的1
1 class Solution { 2 public int findComplement(int num) { 3 int maxbit = 1; 4 int x = num; 5 while(x != 0){ 6 //找最右边第一位1 7 maxbit = x & (-x); 8 x = x & (x -1); 9 } 10 return num ^ ((maxbit << 1) - 1); 11 12 } 13 }