基础算法学习:位运算
精简总结:
&:按位与,1&0=0,0&1=0,0&0=0,1&1=1,只有都为1时才为1.
|:按位或,1|1=1,1|0=1,0|1=1,0|0=0,只有都为0时才为0.
^:按位异或,1^1=0,1^0=1,0^a=a,相同为0,不同为非0的那个数.
>>:右移,a>>x,表示a除以2^x;
<<:左移,a<<x,表示a乘2^x;
~:把0变成1,把1变成0;
-x=~x+1;
(1)lowbit(x)
将十进制数的二进制表示的最低位1取出来。
int lowbit(int x)
{
return x&-x;
}
如x的二进制表示时100,-x在计算机中为~x+1,则~x=011,~x+1=111,那么就有
(100)&(111)=(100),这样就可以把最低位上面的1取出来。
(2)把n对应二进制表示中第k位取出来(注意有第0位)
int get(int n,int k)
{
return n>>k&1;
}
(3)输出所有小于k的十进制
for(int i=0;i<1<<k;i++)
cout<<i;
详细介绍:
位运算基础与常见操作
位运算是对数字的二进制位进行的操作,常用于需要高效处理数据、节省时间和空间的场景。通过位运算,我们可以实现许多常见的算法优化,尤其是在与数学和计算机内部存储结构相关的算法中。下面我们将介绍几种常见的位运算及其应用。
1. 常见的位运算符
位运算符主要有以下几种,每种操作的含义都与二进制位的操作相关。
-
按位与(&) :
a & b
操作会对a
和b
的每一位进行“与”运算,只有两个操作数的相同位都为1时,结果才为1,否则为0。
例子:5 = 0101 3 = 0011 ------------ 5 & 3 = 0001 // 结果为 1
-
按位或(|) :
a | b
操作会对a
和b
的每一位进行“或”运算,只有两个操作数的相同位都为0时,结果才为0,否则为1。
例子:5 = 0101 3 = 0011 ------------ 5 | 3 = 0111 // 结果为 7
-
按位异或(^) :
a ^ b
操作会对a
和b
的每一位进行“异或”运算,两个操作数相同的位为0,不同的位为1。
例子:5 = 0101 3 = 0011 ------------ 5 ^ 3 = 0110 // 结果为 6
-
右移(>>) :
a >> x
操作会将a
的二进制表示向右移动x
位,相当于对a
进行除以2^x
。
例子:8 = 1000 8 >> 2 = 0010 // 结果为 2
-
左移(<<) :
a << x
操作会将a
的二进制表示向左移动x
位,相当于对a
进行乘以2^x
。
例子:2 = 0010 2 << 2 = 1000 // 结果为 8
-
按位取反(~) :
~a
操作会对a
的二进制表示进行按位取反,把0
变成1
,把1
变成0
。
例子:5 = 0101 ~5 = 1010 // 结果为 -6(补码表示)
-
负数的表示(-x) :
在计算机中,负数是以补码形式表示的,-x = ~x + 1
。
例子:x = 5 ~x = 1010 -x = ~5 + 1 = 1010 + 1 = 1011 // 结果为 -5
2. 常见的位运算技巧
(1) lowbit(x)
lowbit(x)
作用是将 x
的二进制表示中最低位的 1 取出来。这在一些算法中,尤其是与树状数组(Fenwick Tree)相关的算法中非常有用。
代码实现:
int lowbit(int x) {
return x & -x;
}
原理:
-
-x
是x
取反加 1,即补码表示。 -
x & -x
结果就是保留最低位的 1,其他位为 0。
例子:
x = 12 = 1100 (二进制)
-x = 4 = 0100
x & -x = 1100 & 0100 = 0100 // 结果为 4
(2) 取出二进制表示中的第 k 位
如果你想获取一个整数 n
在二进制表示中第 k
位的值(0 或 1),可以通过右移 k
位然后与 1 进行按位与来实现。
代码实现:
int get(int n, int k) {
return (n >> k) & 1;
}
例子:
n = 12 = 1100 (二进制)
k = 2
get(12, 2) = (12 >> 2) & 1 = 3 & 1 = 1 // 第 2 位为 1
(3) 输出小于 k 的所有十进制数
若需要输出所有小于 k
的十进制数,可以利用位移运算(1 << k
)来表示范围,遍历所有可能的二进制数。
代码实现:
for (int i = 0; i < (1 << k); i++) {
cout << i << endl;
}
例子:
k = 3
输出:
0
1
2
3
4
5
6
7
3. 位运算的实际应用
位运算在许多实际问题中都有应用,特别是在优化性能方面。例如:
- 计算某个数的二进制中 1 的个数:可以利用
x & (x - 1)
的技巧快速消除最低位的 1。 - 判断一个数是否为 2 的幂:
x > 0 && (x & (x - 1)) == 0
。 - 数值范围控制:使用位运算进行数字范围的控制和处理。
4. 总结
位运算是计算机底层的基础操作,它在很多算法中起到至关重要的作用,特别是在需要高效处理数据的场景中。掌握位运算能让你在处理某些问题时更加得心应手,提高程序的效率。
- 位运算操作符常用且直接,理解其原理后可以应用于实际问题中。
- 位运算常常用于优化时间复杂度或空间复杂度,是面试中常见的考点之一。