力扣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;

^:按位异或,若参加运算的两个二进制位值相同则为0,否则为1;

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 }

posted on 2022-08-24 18:28  我不想一直当菜鸟  阅读(95)  评论(0编辑  收藏  举报