先理解与,或,异或
| 符号 | 描述 | 运算规则 |
|---|---|---|
| & | 与 | 两个位都为1,结果才为1 |
| l | 或 | 两个位都为0,结果才为0 |
| 异或 | 两个位相同为0,相异为1 |
算法中常用的位运算操作:
- X & 1 ==1 or ==0 判断奇偶性(X%2==1)
- X=X & (X-1) 清零最低位的1
- X & -X 得到最低位的1
^ 可以被叫做无进制加法,所以异或运算的结果只取决于相同位置上的1的个数。
比如 a ^ b ,如果个位上有1个1,那么各位就为1,如果有两个1,那么个数就为0,其他位置同理。
所以满足交换律: (a ^ b) ^ c =a ^( b ^ c)
还有个特性:N ^ 0 =N , N ^ N =0
1.判断一个数是否是奇数还是偶数
解法一:直接与2取模,看结果是否等于0
public boolean isEven(int x){
return (x % 2) == 0
}
解法二:判断一个数是否为偶数,也就是说判断该数的二进制数最后一位是否为0,任何数与1(二进制的1是0001)做与运算,也就是计算该数的最后一位与1做与运算,只有最后一位为1,那么就为奇数,为0则为偶数。
public static boolean isEven(int x) {
return (x & 1) == 0;
}
2.判断一个数是否是2的N次幂
思路:2的n次幂的二进制数都有一个规律,就是首位为1,其余为都为0。譬如2--10 ,4--100,8--1000,16--10000等等 而上面例子中的x&(x-1)可以清零二进制中最低位一个1
public boolean IsPowerOf(int n) {
return (n & (n - 1)) == 0;
}
3. 花式交换两个不同元素
在很多排序的场景下,都有交换两个元素的操作,一般为下:
public void swap (int[] arr, int i , int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
在这个场景下,就可以利用异或操作来改进一下
public void swap (int[] arr, int i , int j){
arr[i] = arr[i] ^ arr[j];
// 第二步
arr[j] = arr[i] ^ arr[j];
// 第三步
arr[i] = arr[i] ^ arr[j];
}
原理:第二步中,把arr[i]替换成arr[i] ^ arr[j],这里变成arr[j] = arr[i] ^ arr[j] ^ arr[j],满足交换律,变成arr[j] = arr[i] ^ (arr[j] ^ arr[j] )。
由于N ^ N =0,所以arr[j] = arr[i] ^ 0 =arr[i];第三部分析同上。
要注意,这里的 i != j,要不然 arr[i] = arr[i] ^ arr[j] 就等于 0 。实际场景中还是不建议玩这种骚操作。 切记!!!