有苦有乐的算法 --- 一个数组中,有两种数出现了奇数次,其余数都出现了偶数次,找到这两种数
题目
一个数组中,有两种数出现了奇数次,其余数都出现了偶数次,找到这两组数
例:
[2,4,3,2,5,4] ⇒ [3,5]
[1,4,6,3,7,8,3,2,1,2,6,6,7,8] ⇒ [6,4]
解析
异或:0^N=N;N^N=0;(a^b)^c=a^(b^c)
假设满足条件的数组:[2,4,3,2,5,4] ;
用0去异或数组中每一个数
0^2^4^3^2^5^4 = 0^(2^2)^(4^4)^3^5=3^5,可得:
一个满足条件的数组,这两个出现了奇数次的数记为a和b;0异或这个数组可以可得到a异或b的结果,并且这个结果不会为0;
这个转换成二进制,取任意一个位置的1,这个位置记为i,对于这两个数来说,这个位置的数必然是一个为1一个为0;
可以把这个数组分成两部分,i位置为1的数为一部分,i位置为0的数为另一部分,a和b不可能位于同一部分,相同的数一定位于同一部分;
对于任意一部分来说,问题就成了有一种数出现了奇数次,其余数都出现了偶数次(点击查看解析);
得出这个数,再用这个数异或上述得到的a异或b的结果,可得另一个数。
代码
public static void printOddTimesNum2(int[] arr) {
int eor = 0;
for (int i = 0; i < arr.length; i++) {
eor ^= arr[i];
}
// [提取出最右的1(点击查看解析)](https://wwp666.blog.csdn.net/article/details/120955604)
int rightOne = eor & (-eor);
int onlyOne = 0; // eor'
for (int i = 0 ; i < arr.length;i++) {
if ((arr[i] & rightOne) != 0) {
onlyOne ^= arr[i];
}
}
System.out.println(onlyOne + " " + (eor ^ onlyOne));
}
浙公网安备 33010602011771号