携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第20天,点击查看活动详情
一、题目描述:
对整数的二进制表示取反(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 < 2^31
二、思路分析:
-
前导零的存在。
根据题目的要求,我们需要将 nn 二进制表示的每一位取反。
然而在计算机存储整数时,并不会仅仅存储有效的二进制位。
例如当 n = 5 时,它的二进制表示为 (101)2 ,而使用 32位整数存储时的结果为:
(0000000000000000000000000000~0101)2
因此我们需要首先找到 nn 二进制表示最高位的那个 11,再将这个 11 以及更低的位进行取反。 -
找到有效高位,s为最高位1的位置。
-
从最低位开始取反。
num右移,&(与)1操作是为了取最低位的那个数字。
当最低位为0时,取反为1,对结果产生影响,则使ans和(1<<i)进行或运算。
或运算将当前位的取反后的1并入ans。
三、AC 代码:
class Solution {
public int findComplement(int num) {
//先找到最高位为1 的位置
int s =-1;
for(int i = 31;i>=0;i--){
if(((num>>i)&1) == 1){
s= i;//s为最高位1的位置。
break;
}
}
//s为最高位1的位置。现在需要将s之后的所有低位取反加入ans
//只有当是0取反为1时,对ans才有影响。从最低位开始判断。
int ans = 0;
for(int i = 0;i<s;i++){
if( ( (num>>i)&1 )!= 1 ){//num右移,&(与)1操作是为了取最低位的那个数字。当最低位为0时,取反为1,对结果产生影响,则使ans和(1<<i)进行或运算。
ans |= (1<<i);//或运算将当前位的取反后的1并入ans。
}
}
return ans;
}
}