数字的补数

给你一个 正整数 num ,输出它的补数。补数是对该数的二进制表示取反。

直观想法,直接取反不就完事了吗

class Solution {
public:
    int findComplement(int num) {
        return ~num;
    }
};

不对的!因为int类型的数据采用四个字节,即32位来储存,前面还有一堆0呢,这堆0也会被取反(第一位变成1所以变成了一个负数),那么应该怎么做呢?
一种方法是将其变成2进制数(进制转换),取反后再变回来;
一种思路是用异或;

方法1:使用位运算
1^1 = 0
1^0 = 1
要处理5,即0000 0101,先搞一个全为1的mask 1111 1111,这个依次<<1,变成1111 1110->1111 1100->1111 1000,变为这个数的时候,直接进行&操作就变成了0000 0000.再将这个mask取反后与原数字异或即可,即 0000 0111 ^ 0000 0101 = 0000 0010.即为所求。
如何获得一个1111 1111呢,这个数其实就是 -1 -1->1000 0001(原码)->1111 1110(反码)->1111 1111(补码)

class Solution {
public:
    int findComplement(int num) {
    unsigned mask = INT_MAX;
    while(mask & num){
        mask = mask<<1;
    }
    return (~mask) & (~num);
    }
};
posted @ 2021-10-18 10:58  Maxwell'Maxwill  阅读(257)  评论(0编辑  收藏  举报