what and how 异或运算

288 阅读2分钟

1. 异或运算

1.1 定义

异或是一个数学运算,用于逻辑运算。如果 a、b 两个值不同,则异或结果为 1 ,否则结果为 0 。真值表如下:

简而言之就是,相同为0,不同为1。

异或运算满足交换律、结合律。

1.2 应用

1.2.1 swap函数

原理如下:

假设 i = 甲 ,j = 乙

ps:①任何数与0异或都为那个数;② i位置 ≠ j位置,否则会被一起洗成0,如下图。

1.2.2 出现奇偶次问题

1.2.2.1 只有一种数出现奇次

问题:对于一个数组,其中只有一种数出现了奇数次,其他所有数都出现了偶数次

要求:时间复杂度为O(N),空间复杂度为O(1)

代码如下:

// 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);
	}

1.2.2.2 两种数出现奇次

问题:对于一个数组,其中有两种数出现了奇数次,其他所有数都出现了偶数次

要求:时间复杂度为O(N),空间复杂度为O(1)

代码如下:

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 );  // 提取出最右的1
		
		
		int eor1 = 0;  // eor'
		for(int i = 0 ; i<arr.length ; i++) {
		//arr[1] =  111100011110000
		//rightOne=  000000000010000
			if((arr[i]& rightOne)!=0) {
				eor1 ^= arr[i];
			}
		}
		System.out.println( eor1 + " " +( eor ^ eor1 ));
		
	}

总源程序如下:


public class EvenTimeOddTimes {
	
	// 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);
	}
	
	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 );  // 提取出最右的1
		
		
		int eor1 = 0;  // eor'
		for(int i = 0 ; i<arr.length ; i++) {
		//arr[1] =  111100011110000
		//rightOne=  000000000010000
			if((arr[i]& rightOne)!=0) {
				eor1 ^= arr[i];
			}
		}
		System.out.println( eor1 + " " +( eor ^ eor1 ));
		
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] arr1= {1,2,3,3,5,5,1,1,2};
		printOddTimesNum1(arr1);
		int[] arr2 = { 1,5,6,6,5,5,5,1,2,3,3,3 };
		printOddTimesNum2(arr2);

	}

}