位运算基本内容与例题
Leetcode 201 数字范围按位与
201. 数字范围按位与
思路1
我们求 & 运算,最开始想到的暴力方法,将每个数字与运算过一遍
示例1:
ans = 5 & 6 & 7
code
int bit(int m , int n )
{
int result = m;
for(int i = m + 1 ; i <= n ; i++ )
{
result = result & i;
}
return result;
}
注意result初始化为m,而不是0,想想为什么?
因为如果设置
result = 0;
0 & i = 0; // 0 & 任何东西都 = 0
不过该方法超时…
思路2
我们假设两个二进制
m: 1001 0110
n: 1001 1010 //m < n
可以发现m -> n的所有数 ,前四位都是不变的
而后四位发生变化
所以我们从开始不同 与 相同的地方 设为分界点
m: 1001 | 0110
n: 1001 | 1010 //m < n
所以就必定有
m : 0 xxxxxxx
n : 1 xxxxxxx
由 [m,n] 区间 一定存在
m : 0 1111
n : 1 0000 // 极端情况 m = 0 1111 n = 1 0000
**所以 m & n = 0 **
**这之后就全是0!!( 0 & 啥) == 0 **
所以,我们最后只需要找到
m 和 n 开始相同的位就可以了!!
code
int rangeBitwiseAnd(int m, int n){
int count = 0 ; //记录位置
while( m != n )
{
m >>= 1;
n >>= 1; // 找到m == n 的位
count++;
}
return m << count; //左移补0
}
end…
位运算的内容
& 、 | 、 ^ 、>> 、 << 、~
1、与运算&
1)两个都是1,结果才是1
2)可以用来判断奇偶
if( ( a & 1 ) == 1 )
if( ( a % 2 == 0 ))
//两句等效
3)取指定位置的数
1111 0110 //取后四位
& 0000 1111
______________
0000 0110
//与运算取得后四位
2、或运算 |
1)两个0,才是0
2)设置为1/0
//后四位设置为1
1101 0101
| 0000 1111
______________
1101 1111
//设置为1
3、异或运算 ^
1)
0^0 =0 0^1=1 1^0=1 1^1=0 a^a = 0 a^0 = a
2)无中间变量交换两个数
int a = 1 ;
int b = 2;
a = a^b; //a = a^b b = b
b = a^b; //a = a^b b = a^b^b , 由上面的性质b^b = 0 -> b = a^0 = a;
a = a^b; //a = a^b^a ,同上 a = b , b = a;
3)查找一堆数里面一个数出现了奇数次,其他数出现了偶数次,这个奇数次的是啥
int eor = 0;
int a[i] = { 5 , 1 ,2 ,3, 4, 4, 5 ,2 , 1};
for(int i = 0 ; i < sizeof(a) / sizeof(int) ; i++ )
{
eor ^= a[i];
}
printf("%d",eor);
//eor = 3
4)取出二进制中最右侧的1
N = 0011 0101 1100
~N = 1100 1010 0011
~N+1 = 1100 1010 0100
//N&(~N + 1 ) ---> 0000 0000 0100
5)二进制里有几个1
int N = 16;
int count = 0;
while( N != 0 )
{
int right = N & (~N + 1);
count++;
N ^= right; //异或掉,都是1 ,则最右侧的1->0;
}
4、取反~
~1 = 0
~0 = 1
5、右移>>
将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃
1110 0011
// a >>= 1;
1111 0001
6、左移<<
将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)
1010 1110
// a = a << 2;
1011 1000