目录
在实际中,由于计算机采用的是二进制存储,所以关于位运算的操作能够实现并简化很多复杂问题。
一、位运算总共有5总运算:
与(&)、或(|)、异或(^)、左移(<<)、右移(>>)。
二、每种运算都有相应的性质:
1.与:都真才真。任何数与0相与都为0,任何数与1相与都为其本身;
2.或:都假才假。任何数与0相或都为其本身,任何数与1相或都为1;
3.异或:任何数与1异或得到其相反数,任何数与0异或得到其本身,任何数与自身异或结果为0;
(1)交换律: A ^ B = B ^ A
(2)结合律: ( A ^ B ) ^ C = A ^ ( B ^ C )
(3)自反性: A ^ B ^ B = A (由结合律可推: A ^ B ^ B = A ^ ( B ^ B ) = A ^ 0 = A)
所以异或能完成数之间的交换以及排除偶次重复:
//a与b的交换
a = a ^ b; // a = 3 ^ 7
b = a ^ b; // b = (3 ^ 7) ^ 7 = 3 ^ (7 ^ 7) = 3 完成b = a
a = a ^ b; // a = (3 ^ 7) ^ (3 ^ 7 ^ 7) = (3 ^ 3) ^ (7 ^ 7) ^ 7 = 7 完成a = b
// 常规方法:通过二次循环找出不重复的数字
for (...) {
for (...) {
...
}
}
// 异或方法:将所有整数异或,出现偶数次的整数会被抵消,最终留下不重复整数。
int result = 0;
for (int index = 0; index < numArray.length; index++) {
result = result ^ numArray[index];
}
return result;
4.左移与右移
效率比乘除高,但是要注意一点:
在二分法中,求中点的时候,不能(left+right)>>2;因为直接相加可能溢出,最好用下面的方式。
int left, right, mid;
mid = left + (right - left)/2;
三、位运算基础上扩展的一些解法
1.统计一个数中1的个数:
while(n){
n = n&(n-1);
++res;
}
return res;
比如两个数的汉明距离,可以先异或再统计1的个数
class Solution {
public:
int hammingDistance(int x, int y) {
//先异或得到结果n
//统计结果n中1的个数 n与n-1位与一次能消除掉n最右边的1
int n = x^y;
int res = 0;
while(n){
n = n&(n-1);
++res;
}
return res;
}
};