文章目录
- 一、两道算法题
- 二、异或运算 介绍
- 三、算法解题思路
- 1、求1个单数出现的数值。
- 2、求2个单数出现的数值。
- 四、算法解题代码
一、两道算法题
(如:1、2、3、2、1、4、4,这里面只有3只出现了1次,是单数出现的)
要求:时间复杂度 O(N) 空间复杂度O(1)
二、异或运算 介绍
如果a、b两个值不相同,则异或结果为1。. 如果a、b两个值相同,异或结果为0。异或也叫半加运算,其运算法则相当于不带进位的二进制加法。
计算示例如下:
a = 4, b = 9
a^b的表达式为
0100
1001
-----
1101
运算规则:
1、0 ^ N = N ; N ^ N = 0
2、a ^ b = b ^ a
3、(a ^ b) ^ c = a ^ (b ^ c)
实际应用(借用上面的运算规则理解):
/**
* 交换数值(用于理解异或运算,但是不建议这样交换数值)
*
* @param a 参数
* @param b 参数
*/
private static void swap(int a, int b) {
a = a ^ b; //a = a ^ b; b = b
b = a ^ b; //a = a ^ b; b = (a ^ b) ^ b = a
a = a ^ b; //a = (a ^ b) ^ a = b; b = a
System.out.println(a + " " + b);
}
三、算法解题思路
1、求1个单数出现的数值。
定义一个全局变量:int eor = 0;
遍历整个数组中的值,分别和eor进行异或。最终eor的值就是这个单数的数值。
(相同的数值异或为零,所以出现了偶数次的数值都被抵消掉了,最终剩下的即是答案。)
2、求2个单数出现的数值。
(假设这两个值分别为a b)
重复刚刚解题1的步骤,将双数的值抵消掉,最终eor的值为a^b;
因为是答案是2个单数,所以这两个值肯定不相等。即a^b != 0;
所以a^b在某一位上肯定为1,(a = 1,b = 0 或 a = 0, b = 1)
因为eor=a^b,所以看eor哪一位为1,取出来这一位。(假设eor = 6,那么eor二进制位:0110,取最右边第一个1,即为2)
由此,通过上一步取出来的这一位,假设为2,那么将所有的数值与2进行与运算(与运算结果为0或者2),可以得到两个子集合(a和b肯定分别在这两个集合中,相同的数值肯定在同一个集合)。
这两个集合的元素分别进行异或运算,最终两个集合都会只剩下一个值,即是我们求的两个值。
四、算法解题代码
未完待续