位运算
竞赛/基础
位运算知识点总结
目录
基本运算符
1. 左移运算符 <<
int a = 5; // 二进制 00000101
int b = a << 2; // 二进制 00010100 → 十进制20
- **功能**:将二进制数所有位向左移动,低位补0
- **数学意义**:相当于乘以2ⁿ(n为移动位数)
2. 右移运算符 >>
int a = 20; // 二进制 00010100
int b = a >> 2; // 二进制 00000101 → 十进制5
-
功能:将二进制数所有位向右移动
-
注意:对有符号数,高位补符号位(算术右移);对无符号数补0(逻辑右移)
3. 按位取反 ~
int a = 5; // 00000101
int b = ~a; // 11111010 → -6(补码表示)
4. 按位与 &
6 & 3 = 2 // 0110 & 0011 = 0010
5. 按位或 |
6 | 3 = 7 // 0110 | 0011 = 0111
运算符性质
交换律
a & b = b & a
a | b = b | a
结合律
(a & b) & c = a & (b & c)
(a | b) | c = a | (b | c)
分配律
a & (b | c) = (a & b) | (a & c)
a | (b & c) = (a | b) & (a | c)
特殊性质
-
幂等律:
a & a = a,a | a = a -
吸收律:
a | (a & b) = a,a & (a | b) = a -
德摩根定律:
~(a | b) = ~a & ~b,~(a & b) = ~a | ~b
经典例题
例题1:表达式计算
(15 >> 2) & (~(1 << 3)) = ?
解答:
-
15 >> 2 = 3(二进制0011) -
1 << 3 = 8(二进制1000) -
~(8) = -9(二进制补码11110111) -
3 & (-9) = 3(00000011 & 11110111 = 00000011)
例题2:位运算应用
题目:用位运算判断奇偶
bool isOdd(int n) {
return n & 1; // 结果为1时是奇数
}
例题3:变量交换
a ^= b;
b ^= a;
a ^= b; // 不使用临时变量交换a,b的值
GESP真题精选
2023年三级样题
题目:执行 (12 & 9) | (5 << 2) 的结果是?
A) 20
B) 21
C) 24
D) 25
解析:
-
12 & 9 = 8(1100 & 1001 = 1000) -
5 << 2 = 20(0101 → 10100) -
8 | 20 = 20(001000 | 10100 = 10100)
答案:A
2023年四级真题
题目:表达式 ~(0xFF << 4) 的二进制结果中最低的8位是?
A) 00001111
B) 11110000
C) 00000000
D) 11111111
解析:
-
0xFF = 11111111 -
<< 4 → 11110000 -
~ → 00001111
答案:A
位运算实用技巧大全
高效计算技巧
1. 快速乘除2的幂
n << 1; // n*2
n >> 1; // n/2(向下取整)
n << 3; // n*8 (2³)
2. 判断奇偶性
if(n & 1) {
// 奇数(二进制末位为1)
} else {
// 偶数
}
3. 交换变量值(无需临时变量)
a ^= b;
b ^= a;
a ^= b;
4. 取绝对值(32位整数版)
int abs(int n) {
return (n ^ (n >> 31)) - (n >> 31);
}
状态压缩应用
1. 集合表示(每个bit代表一个元素)
int set = 0;
set |= (1 << 3); // 添加第3个元素
set &= ~(1 << 3); // 删除第3个元素
bool has = set & (1 << 3); // 检查第3个元素
2. 遍历子集
for(int subset = set; subset; subset = (subset-1) & set) {
// 处理subset
}
3. 低效版(仅演示原理)
// 获取数字的二进制1的个数(汉明重量)
int count = 0;
while(n) {
count += n & 1;
n >>= 1;
}
算法优化技巧
1. 快速幂算法
int pow(int x, int n) {
int res = 1;
while(n) {
if(n & 1) res *= x;
x *= x;
n >>= 1;
}
return res;
}
2. 检测2的幂次
bool isPowerOfTwo(int n) {
return n > 0 && (n & (n - 1)) == 0;
}
3. 最低有效位(LSB)
int lsb = n & -n; // 获取最右边的1
奇技淫巧
1. 字符大小写转换
char lower = ch | ' '; // 转小写
char upper = ch & '_'; // 转大写
char toggle = ch ^ ' '; // 大小写互换
2. 条件语句替代
// 代替 if(a>b) swap(a,b)
int diff = a ^ b;
int mask = (a - b) >> 31;
a ^= diff & mask;
b ^= diff & mask;
3. 模运算优化(仅适用于2ⁿ-1)
int mod = n & 0x0F; // 等价于 n % 16
实战例题
例题1:找唯一出现数字
题目:数组中除一个数字出现1次外,其他都出现2次,找出该数字
int singleNumber(vector<int>& nums) {
int res = 0;
for(int num : nums) res ^= num;
return res;
}
例题2:汉明距离
题目:计算两个整数二进制位不同的位数
int hammingDistance(int x, int y) {
int diff = x ^ y, count = 0;
while(diff) {
diff &= diff - 1;
count++;
}
return count;
}
例题3:位图排序
题目:对0-99的不重复数字排序(内存限制1KB)
unsigned char bitmap[16]; // 16*8=128bit
// 设置bit位
bitmap[n/8] |= (1 << (n%8));
// 检查bit位
if(bitmap[i/8] & (1 << (i%8)))
重要提示:位运算技巧虽然高效,但会降低代码可读性,实际开发中需权衡使用,建议添加详细注释说明原理。

浙公网安备 33010602011771号