位运算(异或+与)的妙用

前言

真正在公司中的实践:NoSQL + RDBMS 一起使用才是最强的,阿里巴巴的架构演进! 技术没有高低之分,就看你如何去使用!(提升内功,思维的提高!) 云计算的长征之路:阿里云的这群疯子

1. 异或 ^

无进位相加,满足交换律 结合律
0^N == N        N^N == 0

1.1 如何不用额外变量交换两个数

int a = 16;
		int b = 61;
		System.out.println("a交换前的值为:"+a);
		System.out.println("b交换前的值为:"+b);
		
		a = a ^ b;
		b = a ^ b;
		a = a ^ b;
		System.out.println("a交换后的值为:"+a);
		System.out.println("b交换后的值为:"+b);

1.2 —个数组中有一种数出现了奇数次,其他数都出现了偶数次,找到并打印这种数

	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时,结果才为1

2.1 把一个int类型的数,提取出最右侧的1来

    int eor = 10;
    // ~eor 取反
	int rightOne = eor & (~eor+1); //rightOne = 2
	// 10  -> 1010
	//~10  -> 0101
	//~10+1-> 0110
//10 & (~10+1) = 0010=2

3. 异或&与^结合的奇妙例子

3.1 统计二进制1的个数

public static int bit1counts(int N) {
    
    
		int count = 0;
		//   011011010000
		//   000000010000     1
		
		//   011011000000
		// 
		while(N != 0) {
    
    
			int rightOne = N & ((~N) + 1);
			count++;
			N ^= rightOne;
			// N -= rightOne
		}
		return count;
	}

3.2 —个数组中有两种数出现了奇数次,其他数都出现了偶数次,找到并打印这两种数

// arr中,有两种数,出现奇数次。假设两数为a与b
	public static void printOddTimesNum2(int[] arr) {
    
    
		int eor = 0;
		for (int i = 0; i < arr.length; i++) {
    
    
			eor ^= arr[i];
		}
		// a 和 b是两种数
		// eor != 0 因为a^b!=0
		// eor最右侧的1,提取出来
		// eor :     00110010110111000
		// rightOne :00000000000001000
		int rightOne = eor & (-eor+1); // 提取出最右的1
		//此时,两奇数a,b与其对应的偶数,已根据rightOne分离开来
		
		int onlyOne = 0;
		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));
	}

猜你喜欢

转载自blog.csdn.net/ws13575291650/article/details/113405686
今日推荐