(leetcode)位运算 Number Complement

来源:互联网 发布:看耽美小说软件 编辑:程序博客网 时间:2024/05/17 21:38


题目是实现将一个int 型数转化,转化方式如下:

如 5 是  101  翻转后是 010  也就是2

如  8 是 1000  翻转后是 0111 也就是7


实现方法一:

int findComplement(int num) {
        unsigned mask=~0;
        while(mask&num) mask<<=1;
        return mask^~num;

    }

假设num=5 ,~num就是0xfffa; 把多余的位去掉就是答案

mask=0  ~mask=0xffff;

while(mask&num) mask<<=1;     结果mask=0xfff8;  多余的位全是1

剩下只需要再做一次异或,去掉多余的位  mask^~num

实现方法2 

int findComplement(int num)

{

mask=num;

mask|=mask>>1;

mask|=mask>>2;

mask|=mask>>4;

mask|=mask>>8;

mask|=mask>>16;

return mask^num;

}

假设num=1001,目的使mask为1111,这样mask^num 就能直接得到结果。

为什么这样就能得到1111呢

考虑最极端也就是1最少的情况,num=1000,(为什么不是0100,因为这样根据要求num=100)

每做一次运算,1的个数加倍,经过以上5步运算总能达到1111,要是0x8000运行5步刚好32个1.

最后做一次异或就能得到结果了。

实现方法3

int findComplement(int num)

{

return ~num & ((1 <<(int)log2(num))-1);

}

这里和方法2的思路是一样的,(int)log2(num)+1是二进制的位数。 假设

num=1001 (1 <<(int)log2(num))-1 快速求出掩码1111

实现方法4


int findComplement(int num)

{

for(long i=0;i<=num;i*=2) num^i;

return num;

}

这里逐位进行翻转,单步算一算应该能明白

这里注意为什么i 为long 而不是int

注意num最大 0-1<<31-1

若i为int,1<<32为0,重复循环









0 0