一、异或运算
特点
N ^ 0 = N 任何数异或0等于这个数本身 N ^ N = 0 任何数异或自身等于0 N ^ M ^ N = N ^ N ^ M = M 异或运算满足交换律与结合律
交换2个数问题
a = a + b; b = a - b; a = a - b;
arr[i] = arr[i] ^ arr[j]; arr[j] = arr[i] ^ arr[j]; arr[i] = arr[i] ^ arr[j];
注意:数组中同一个位置的会有问题
二、数组中找出出现奇数次的数问题
只有一个数出现奇数次
根据异或运算特点,对数组每一个元素进行异或运算,运算后的结果即是次奇数次的元素
public int findOdd(int[] arr) { int eor = 0; for(int i = 0; i < arr.length; i++) { eor ^= arr[i]; } return eor; }
2个数出现奇数次
根据异或运算特点,数组中每个元素进行异或运算后的结果肯定是出现两种奇数次元素的异或结果,且此结果肯定不为0,那么就一定在二进制位上存在一个1位,找到最右侧的1位,将原数组根据元素此位是否为1进行分组异或,得出其中一个出现奇数次的数,然后根据第一次的异或结果得出第二个奇数次的数
public int[] findOdd(int[] arr) { int eor = 0; for(int i = 0; i < arr.length; i++) { eor ^= arr[i]; } // 提取出 eor 最右侧的1 int rightOne = eor & (- eor); int one = 0; for(int i = 0; i < arr.length; i++) { if((arr[i] & rightOne) != 0) { one ^= arr[i]; } } int other = eor ^ one; return new int[]{one, other}; }
三、二进制相关内容
求一个数的二进制最右侧的1位
// N : 0000 1011 1010 1000 //~N : 1111 0100 0101 0111 //~N+1 : 1111 0100 0101 1000 //-N == ~N + 1 : 1111 0100 0101 1000 int N = 10; int rightOne = N & (-N); boolean r = ((N & (-N)) == (N &((~N) +1)));
统计一个数二进制位的个数
public int bitCount(int N) { int count = 0; while(N != 0) { int rightOne = N & ((~N) + 1); // 找到最右侧的1,同 N & (-N) count++; N ^= rightOne; // 同 N -= rightOne; } return count; }
一个数的二进制表示
public String bitString(int N) { StringBuilder s = new StringBuilder(); if(N == 0) { return "0"; } int one = 1; // 0001 0110 while(N != 0) { if((N & one) == 0) { s.append("0"); } else { s.append("1"); } N >>= 1; } return s.reverse().toString(); }
四、一种数出现了K次,其他数出现了M次
public static HashMap<Integer, Integer> map = new HashMap<>(); // 请保证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; } public static void mapCreater(HashMap<Integer, Integer> map) { int value = 1; for (int i = 0; i < 32; i++) { map.put(value, i); value <<= 1; } }