问题定义
问题一:在一个数字序列中,有一个数出现了奇数次,其他数都出现了偶数次,找到这个奇数。
问题二:在一个数字序列中,有两个数出现了奇数次,其他数都出现了偶数次,寻找这两个数。
背景知识
在解答这个问题之前,我们先介绍一些背景知识:异或运算
简单来讲,就是相同为0,不同为1,如下所示
1^1=0
0^0=0
1^0=1
0^1=1
此外,异或运算符合两个性质:交换律和结合律,也就是说
a ^ b = b ^ a
a ^ b ^ c = a ^ (b ^ c) = (a ^ b) ^ c;
分析问题
有了上面的背景知识,我们再来分析一下这个问题,该序列中只有一个数出现了奇数次,其他数都出现了偶数次,那么对于异或运算来看,两个相同的数异或,得到0;一个数与0异或,得到的是它本身,现在你懂了吗?
也就是说,对于出现偶数次的哪些数,我们交换顺序(符合交换律)让它们异或,得到0,而剩下的数和0异或还是这个数,不影响运算过程,如下所示:
a ^ b ^ a ^ c ^ c = a ^ a ^b ^ c ^ c = 0 ^ 0 ^ b= b.
看到了吗?我们让所有的数一起异或,出现偶数次的数字会被消除掉,最后只剩下那个出现奇数次的数。
代码示例
代码如下(示例):
/**
* 一个数组中有一个数出现了奇数次,其他数都出现了偶数次,寻找该奇数
* @param arr 数组
*/
public static void problem1(int[] arr){
int res = 0;
for(int value:arr){
res ^= value;
}
System.out.println(res);
}
思考环节
没错,第一题就是如此简单,一个异或运算就可以解决该问题,那么第二个问题呢?你能找到解决办法吗?我会在下一篇文章中讲解第二个问题。
尾注
留下笔记,只为方便回忆,如有侵权,还请联系,如有错误,恳请纠正。陆续更新,还请关注。