文章放置于:https://github.com/zgkaii/CS-Notes-Kz,欢迎批评指正!
位运算基础
位运算符概览
符号 | 描述 | 运算规则 |
---|---|---|
& |
与 | 两个位都为1时,结果才为1 |
| |
或 | 两个位都为0时,结果才为0 |
~ |
非 | ~1 = 0 , ~0 = 1 |
^ |
异或 | 两个位相同为0,相异为1 |
<< |
左移 | 各二进位全部左移若干位,高位丢弃,低位补0 |
>> |
右移 | 各二进位全部右移若干位,对无符号数,高位补0; 有符号数,各编译器处理方法不一样,有的补符号位(算术右移),有的补0(逻辑右移) |
基础应用
按位 与(&)
- 清零:任何一个数字,只要与一个各位都为零的数值相与,结果为零。
- 取一个数的指定位:比如取数
X=1010 1110
的低4位,另找一个数Y=0000 1111
,按位与运算X&Y=0000 1110
即得到X
的指定位。 - 判断奇偶:最末位为0,偶数;最末位为1,奇数。
(a & 1) == 0
代替a % 2 == 0
来判断奇偶。 - 消去x最后一位的1:
x & (x - 1)
。
按位 或(|)
- 来对一个数据的某些位设置为1:比如将数
X=1010 1110
的低4位设置为1,只需要另找一个数Y=0000 1111
,然后将X与Y进行按位或运算X|Y=1010 1111
即可得到。
按位 非(~)
- 使一个数的最低位为零:使a的最低位为0,可表示为:
a&~1
。~1
的值为1111 1111 1111 1110
,再按"与"运算,最低位一定为0。 - 位操作交换符号:正数变成负数,负数变成正数。如
a = ~a + 1
。整数取反加1,正好变成其对应的负数(补码表示);负数取反加1,则变为其原码,即正数。
异或(^)
-
翻转指定位:将数
X=1010 1110
的低4位进行翻转,只需要另找一个数Y=0000 1111
,X与Y进行异或运算X^Y=1010 0001
即得到。 -
与0相异或值不变:例如
1010 1110 ^ 0000 0000 = 1010 1110
。 -
交换两个数:
void Swap(int &a, int &b){ if (a != b){ a ^= b; b ^= a; a ^= b; } }
-
去掉三数中的重复数:
a ^ b ^ b = a
。
位移(<<与>>)
>> n
为算术右移,相当于除以 2n,例如 -7 >> 2 = -2。
11111111111111111111111111111001 >> 2
--------
11111111111111111111111111111110
>>> n
为无符号右移,左边会补上 0。例如 -7 >>> 2 = 1073741822。
11111111111111111111111111111001 >>> 2
--------
00111111111111111111111111111111
<< n
为算术左移,相当于乘以 2n。-7 << 2 = -28。
11111111111111111111111111111001 << 2
--------
11111111111111111111111111100100
Java 中的位操作
static int Integer.bitCount(); // 统计 1 的数量
static int Integer.highestOneBit(); // 获得最高位
static String toBinaryString(int i); // 转换为二进制表示的字符串
实战演练
只出现一次的数字 III
以260. 只出现一次的数字 III为例,给定一个整数数组 nums
,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。你可以按 任意顺序 返回答案。
public int