[异或运算]认识异或运算

基础知识:

异或运算:相同为0,不同为1
同或运算:相同以1,不同为0

能长时间记住的概率接近0%

所以,异或运算就记成无进位相加!

异或运算的性质

0^N == N      N^N == 0
异或运算满足交换律和结合率

上面的两个性质用无进位相加来理解就非常的容易

1.如何不用额外空间交换两个数据?

public static void swap (int[] arr, int i, int j) {
		// arr[0] = arr[0] ^ arr[0];
		arr[i]  = arr[i] ^ arr[j];
		arr[j]  = arr[i] ^ arr[j];
		arr[i]  = arr[i] ^ arr[j];
	}

2. 一个数组中有一种数出现了奇数次,其他数都出现了偶数次,怎么找到并打印这种数

通过我们的基础知识我们可以知道如果一个数出现了偶数次那么它异或之后为0,出现奇数次的那个数就可以被筛选出来。

// arr中,只有一种数,出现奇数次
	public static void printOddTimesNum1(int[] arr) {
		int eor = 0;
		for (int i = 0; i < arr.length; i++) {
			eor ^= arr[i];
		}
		System.out.println(eor);
	}

2.1升级版:arr中,有两种数,出现奇数次

public static void printOddTimesNum2(int[] arr) {
		int eor = 0;
		for (int i = 0; i < arr.length; i++) {
			eor ^= arr[i];
		}
		// a 和 b是两种数
		// eor != 0
		// eor最右侧的1,提取出来
		// eor :     00110010110111000
		// rightOne :00000000000001000
		int rightOne = eor & (-eor); // 提取出最右的1
		
		
		int onlyOne = 0; // eor'
		for (int i = 0 ; i < arr.length;i++) {
			//  arr[1] =  111100011110000
			// rightOne=  000000000010000
			if ((arr[i] & rightOne) != 0) {
				onlyOne ^= arr[i];
			}
		}
		System.out.println(onlyOne + " " + (eor ^ onlyOne));
	}

3.怎么把一个int类型的数,提取出最右侧的1来

公式:,-error = (~error)+1

10 的二进制数: 0000 1010

10 的负数(取反+1),分两步走:

  • 10 二进制取反: 1111 0101
  • 10 二进制取反+1(-10):1111 0110

将10 和 -10 进行与运算
0000 1010
1111 0110
& 运算---------
0000 0010
得到了 10 的二进制位最右边的 1

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值