目录
总结:位运算
基本原理:
- 二进制数在内存中是以补码的形式存放的
- 正数的补码,反码都是其本身,
- 负数的补码是:符号位不变,其余各位求反,末位加1 ;反码是:符号位为1,其余各位求反,但末位不加1 。
0s 表示一串 0,1s 表示一串 1。
x ^ 0s = x x & 0s = 0 x | 0s = x x ^ 1s = ~x x & 1s = x x | 1s = 1s x ^ x = 0 x & x = x x | x = x
- 利用 x ^ 1s = ~x 的特点,可以将位级表示翻转;利用 x ^ x = 0 的特点,可以将三个数中重复的两个数去除,只留下另一个数。
- 利用 x & 0s = 0 和 x & 1s = x 的特点,可以实现掩码操作。一个数 num 与 mask:00111100 进行位与操作,只保留 num 中与 mask 的 1 部分相对应的位。
- 利用 x | 0s = x 和 x | 1s = 1s 的特点,可以实现设值操作。一个数 num 与 mask:00111100 进行位或操作,将 num 中与 mask 的 1 部分相对应的位都设置为 1。
位与运算技巧:
- n&(n-1) 去除 n 的位级表示中最低的那一位。例如对于二进制表示 10110100,减去 1 得到 10110011,这两个数相与得到 10110000。
- n&(-n) 得到 n 的位级表示中最低的那一位。-n 得到 n 的反码加 1,对于二进制表示 10110100,-n 得到 01001100,相与得到 00000100。
- n-n&(~n+1) 去除 n 的位级表示中最高的那一位。
- 计算机中的负数是以其补码形式存在的,负数的补码=原码取反+1,即-n=~n+1
移位运算:
- >> n 为算术右移,低位移出,高位的空位补符号位,即正数补零,负数补1。相当于除以 ;
- >>> n 为无符号右移,忽略了符号位扩展,最高位补0;
- << n 为算术左移,高位移出,低位的空位补零。相当于乘以 。
掩码:(英语:Mask)在计算机学科及数字逻辑中指的是一串二进制数字,通过与目标数字的按位操作,达到屏蔽指定位而实现需求。
- 要获取 111111111,将 0 取反即可,~0。
- 要得到只有第 i 位为 1 的 mask,将 1 向左移动 i-1 位即可,1<<(i-1) 。例如 1<<4 得到只有第 5 位为 1 的 mask :00010000。
- 要得到 1 到 i 位为 1 的 mask,1<<(i+1)-1 即可,例如将 1<<(4+1)-1 = 00010000-1 = 00001111。
- 要得到 1 到 i 位为 0 的 mask,只需将 1 到 i 位为 1 的 mask 取反,即 ~(1<<(i+1)-1)。
Java 中的位操作
- static int Integer.bitCount(); // 统计 1 的数量
- static int Integer.highestOneBit(); // 获得最高位
- static String toBinaryString(int i); // 转换为二进制表示的字符串
以上引自:https://www.cnblogs.com/xiaojiaojiao/p/10706427.html
java中按位取反运算符“~”参考:https://blog.csdn.net/smilecall/article/details/42454471
461. 汉明距离
【题目】:
【代码】:
方法1:对x,y两个数进行异或操作,异或结果转为二进制,统计有多少个 1 即可。
但是效果不太好:
方法2:对x,y两个数进行异或操作,得到ret,ret的二进制每次右移1位与1相与,由于1的高位全为0,1只有与1相与才得到1,统计有多少个 1 即可。
效果:
方法3:使用 z&(z-1) 去除 z 位级表示最低的那一位。
效果:
方法4:使用 Integer.bitcount() 来统计 1 个的个数。
效果:
268. 缺失数字
【题目】:
【代码】:
方法1:用0到n的和减去数组中数的和,提交正确,但是如果实际数组中数据太大可能会有溢出。
效果:
方法2:使用异或运算^进行 抵消,剩下的数字就是缺失的
效果: