有苦有乐的算法 --- 一个数组中,有两种数出现了奇数次,其余数都出现了偶数次,找到这两种数

题目

一个数组中,有两种数出现了奇数次,其余数都出现了偶数次,找到这两组数
例:
[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的结果,可得另一个数。

代码

此代码提取的是最右测的1(点击查看解析)

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));
}
posted @ 2022-03-07 18:03  叕叕666  阅读(86)  评论(0)    收藏  举报