【算法】求数组中出现了奇数次的一种/俩种数(异或运算)
左程云算法与数据结构课 https://www.bilibili.com/video/BV13g41157hK?p=2&spm_id_from=pageDriver
题目描述
在一个数组中,
(1)有一种数出现了奇数次,其余数出现了偶数次,求出现了奇数次的那种数。
(2)有俩种数出现了奇数次,其余数出现了偶数次,求出现了奇数次的俩种数。
题解
(1)一批数进行异或,与异或的顺序无关。
对数组的所有数进行异或,出现偶数次的数进行异或之后是0,出现奇数次的那种数异或之后还是那个数,所以最终异或结果是出现奇数次的那种数。
例如:数组[1,1,2,3,4,2,3,1,4]中除了1出现了奇数次外其余数均出现了偶数次,对数组元素进行异或,1^1^2^3^4^2^3^1^4=1^1^1^2^2^3^3^4^4=1
public static void printOddTimesNum1(int[] arr) {
int eor = 0;
for (int cur : arr) {
eor ^= cur;
}
System.out.println(eor);
}
(2)假设出现了奇数次的俩种数分别是a和b。
对数组元素进行异或,最终结果是a^b。
由于a不等于b,故a^b的二进制中至少有一位为1,假设是第n位为1。
对数组中第n位为1的元素进行异或(以第n位是否为1,可以把数组分成两份,a和b分别落于这两份之中),则结果为出现了奇数次的俩种数中的一种,然后让它和a^b进行异或,则可以求出另一种出现了奇数次的数。
public static void printOddTimesNum2(int[] arr) {
int eor1 = 0,eor2 = 0;
for (int cur : arr) {
eor1 ^= cur;
}
//eor1 = a ^ b
//eor1!=0,其二进制中至少有一个位置为1
// 提取出最右的1
int rightOne = eor1 & (~eor1+1);
for (int cur : arr) {
if ((cur & rightOne) == 1) { //只有第n位是1的才进行异或
eor2 ^= cur;
}
}
System.out.println(eor2 + " " + (eor1 ^ eor2));
}
本文来自博客园,作者:hzyuan,转载请注明原文链接:https://www.cnblogs.com/hzyuan/p/15760173.html

浙公网安备 33010602011771号