Skip to content

异或运算相关面试 ​

1. arr中只有一种数,出现奇数次 ​

  • 1111 22 3333 444
  • 相当于偶数次的异或后都为0,最后只剩了一个4
for (int i = 0; i < arr.length; i++) {
	eor ^= arr[i];
}

2. 提取一个二进制最右边的1 ​

  • a & (-a)

3. arr中有两种数,出现奇数次 ​

  • 一定有两个数a,b,有eor=a^b
  • eor一定不为0,我们取最右边的1
  • 该位上a与b的数值一定不一样,比如这是第三位
  • 那么把整个数组该位上有1的分为一组,无1的分为一组
  • 令新的变量eor1去异或有1的一组,一定可以得到一个数
  • 最后 eor ^ eor1
java
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));
	}

4. 一个数组中有一种数出现K次,其他数都出现M次,K<M,求小的那个数 ​

  • 转换为32位
  • 比如多的数出现了7次,若位运算后第0位上的数字是7的整数倍,那么那个较小的数该位上一定为0
java
// 请保证arr中,只有一种数出现了K次,其他数都出现了M次
	public static int onlyKTimes(int[] arr, int k, int m) {
		if (map.size() == 0) {
			mapCreater(map);
		}
		int[] t = new int[32];
		// t[0] 0位置的1出现了几个
		// t[i] i位置的1出现了几个
		for (int num : arr) {
			while (num != 0) {
				int rightOne = num & (-num);
				t[map.get(rightOne)]++;
				num ^= rightOne;
			}
		}
		int ans = 0;
		for (int i = 0; i < 32; i++) {
			if (t[i] % m != 0) {
				if (t[i] % m == k) {
					ans |= (1 << i);   
				} else {
					return -1;
				}
			}
		}
		if (ans == 0) {
			int count = 0;
			for (int num : arr) {
				if (num == 0) {
					count++;
				}
			}
			if (count != k) {
				return -1;
			}
		}
		return ans;
	}

5. 学一下用对数器DeBug代码 ​