C++位运算题目中常用的一些基本知识

1:异或操作满足交换律且如果 A=B则,A^B=0;

2:  X&1常常用来判断X的最后一位是否为1,同理X&2可用来判断倒数第二位是否为1

3:左右位移操作是返回左值的。所以我们需要保存x左移i位结果时,写成x=(x<<i);

4 :X&(X-1)是将X的最后一位1置为0的操作,这个手法一般用于求只保留最后一位1的数。

很多时候位操作能非常神奇的结局很多问题。

我们来举几个例子:

1 single number

给出2n+1个数字,除唯一一个数字以外,其他的均可找到一对

答案很简单,全部数字做异或操作,结果就是。这里就利用了异或操作的交换律和相同数字异或为0的性质

2 single number2

这次是3n+1,其实也很简单,就是先建立一个32位数组,C++ int 4个字节嘛,遍历每一位的累加和,求mod3然后移动到相应的位置,最后就是结果了。

3 single number3

这次是2n+2,我们知道最后所有数字异或的结果中最后一位1意味着该位两个不同数字互异,所以利用这点,再进行一次遍历异或操作,分为两组一组为在最后一位为1的位置上也为1的数,一组是不为1.这样就把两个不同的数分开了。

4 Determine the power of 2 or 4

确认是否为2的幂时 我们知道所有这样的数中只有一个1只需要确认x&(x-1)是否为0就行,因为这个操作就是把x中最后一个1置0.

确认是否为4的幂时,第一得满足为2的幂。第二得满足1这个一位在奇数位上。x&0x55555555是否为0就行。

5 确认是否为3或者其他的数的幂时,还不一定能用位操作完成,此时应该从int数大小有限制这一点来考虑

比如这个是否为3的幂问题直接看int 32位数中最大的3的幂能否整除该数即可。

6 不用+.-符号求加减

假设int a,int b求它两的和:

long carry;

 

while(b!=0)

{

carry=a&b;

a=a^b;

b=((carry&0x7fffffff)<<1);

}

return a;

 

carry&0x7fffffff这句代码是为了将可能移动到符号位的进位给抵消掉,由于leetcode C++标准不能左移负数。

 

其他的还有很多题目可以讨论,这里就不展开说了。关于位操作的最全说明http://graphics.stanford.edu/~seander/bithacks.html

 

posted @ 2019-08-27 16:08  Tonarinototoro  阅读(303)  评论(0)    收藏  举报