异或运算
不同为 1 相同为0 (也可以理解为无进位相加) (相当于在或运算加了(1)相同为0的限制)
使用异或运算交换数据
// 交换数据// 前提 arr[i] 和 arr[j] 不指向同一个内存地址 否则会等级0arr[i] = arr[i]^arr[j]arr[j] = arr[i]^arr[j]arr[i] = arr[i]^arr[j]
取得最右侧的1
N & (~N + 1)证明:N: 10000100~N: 01111011~N + 1: 0111111N & (~N + 1) : 00000100
任何数异或自身都等于0
- 任何数异或0都等于自身
有交换性 和结合性
0 ^ 0 = 01 ^0 = 1x ^ y = y ^ x(x ^ y) ^ z = x ^ (y ^ z)
可以用来做些简单的加密过程
- 通过明文和密钥进行异或运算 得到密文
密文和明文进行异或运算 得到密钥
text ^ key = cipherTextcipherText ^ key = text
或运算
& 或运算符 只有两个相同才会相同 (理解为两个都要相同)
只有两个都为1的时候 才会为11 & 2 = 01 & 0 = 0
与运算
| 与运算符 只有两个有一个为1 则是1 (理解为只要有一个为1就是1)
只有两个都是0 才是01 | 0 = 1
题目
一个数组中 有两种数字出现了奇数次 其他数都出现了偶数次 怎么找出并打印这两个数字
public static void searchOdd(int arr[]) {int flag = 0; // 0 异或任何数都等他们本身for (int i = 0; i <arr.length ; i++) {flag ^= arr[i];}// 此时falg 为 a ^ bint rightOne = flag & ((~flag) + 1);int resultOne= 0,resultTwo = 0;// rightOne 为最右侧的一个1 因为有两个数为奇数而且不等则他们一定有一位数不相同 且 这个1就是他们(a^b)最先不同的位数for (int i = 0; i < arr.length; i++) {// 确定这一位上为1if((rightOne & arr[i]) !=0) {resultOne ^=arr[i];}else {// 确定这一位上为0resultTwo ^= arr[i];}}System.out.println(resultOne);System.out.println(resultTwo);}
一个数中的1的个数有多少个
public static int oneNumbers(int number) {int count = 0;int flag = 0;while (number != 0) {flag = number & ((~number) + 1);count++;// 将这个1重置为0number = flag ^ number;}return count;}
右移运算符
int middle = (int) pre +((next - pre) >> 1)// >> 1相当于除了一个2
