面试题:异或去重

来源:http://blog.csdn.net/ns_code/article/details/27568975

异或是一种基于二进制的位运算,用符号XOR或者 ^ 表示,其运算法则是对运算符两侧数的每一个二进制位,同值取0,异值取1。它与布尔运算的区别在于,当运算符两侧均为1时,布尔运算的结果为1,异或运算的结果为0。

异或的性质:满足交换律和结合律

1、交换律:a^b = b^a;

2、结合律:(a^b)^c = a^(b^c);

3、对于任意的a:a^a=0,a^0=a,a^(-1)=~a。

了解了上面这些,来看看这个,很重要,后面的程序都要用到这个结论:
如果有多个数异或,其中有重复的数,则无论这些重复的数是否相邻,都可以根据异或的性质将其这些重复的数消去,具体来说,如果重复出现了偶数次,则异或后会全部消去,如果重复出现了奇数次,则异或后会保留一个。

下面来看两道题目:

1、1-1000放在含有1001个元素的数组中,只有唯一的一个元素值重复,其它均只出现一次。每个数组元素只能访问一次,设计一个算法,将它找出来;不用辅助存储空间,能否设计一个算法实现?

当然,这道题,可以用最直观的方法来做,将所有的数加起来,减去1+2+3+...+1000的和,
得到的即是重复的那个数,该方法很容易理解,而且效率很高,也不需要辅助空间,唯一的不足时,如果范围不是1000,而是更大的数字,可能会发生溢出。
 如果我们能想办法把1-1000中除n以外的数字全部异或两次,而数字n只异或一次,就可以把1-1000中出n以外的所有数字消去,这样就只剩下n了。
 我们首先把所有的数字异或,记为T,可以得到如下:
T = 1^2^3^4...^n...^n...^1000 = 1^2^3...^1000(结果中不含n)
而后我们再让T与1-1000之间的所有数字(仅包含一个n)异或,
便可得到该重复数字n。如下所示:T^(a^2^3^4...^n...^1000) = T^(T^n) = 0^n = n

这道题到此为止。

但是,当这道题这样变化之后呢:1-1000及N(N為任意整數)放在含有1001个元素的数组中,最多有一个元素值重复,其它均只出现一次,求出N的值?
答案:依然可以从上面的两种方法。只是用异或的时候直接与1^2…^1000异或即可得到结果。

2、一个数组中只有一个数字出现了一次,其他的全部出现了两次,求出这个数字。

明白了上面题目的推导过程,这个就很容易了,将数组中所有的元素全部异或,最后出现两次的元素会全部被消去,而最后会得到该只出现一次的数字。

该题目同样可以该为如下情景,思路是一样的:数组中只有一个数字出现了奇数次,其他的都出现了偶数次。

你可能感兴趣的:(面试题,异或去重)