算法笔记 -- 476. 数字的补数

70 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第20天,点击查看活动详情

一、题目描述:

476. 数字的补数

对整数的二进制表示取反(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

二、思路分析:

  1. 前导零的存在。
    根据题目的要求,我们需要将 nn 二进制表示的每一位取反。
    然而在计算机存储整数时,并不会仅仅存储有效的二进制位。
    例如当 n = 5 时,它的二进制表示为 (101)2 ,而使用 32位整数存储时的结果为:
    (0000000000000000000000000000~0101)2
    因此我们需要首先找到 nn 二进制表示最高位的那个 11,再将这个 11 以及更低的位进行取反。

  2. 找到有效高位,s为最高位1的位置。

  3. 从最低位开始取反。
    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;
    }
}