链接:面试题 17.19. 消失的两个数字
代码:
class Solution {public int[] missingTwo(int[] nums) {int length=nums.length;int tmp=0;//将完整数据以及 nums 中的数据都进行异或,得到的就是缺失的两个数字 a^b 的结果for(int i=1;i<=length+2;i++){tmp^=i;}for(int i=0;i<length;i++){tmp^=nums[i];}//tmp 里的内容是 a^b (a,b 是缺失的两个数字)要分开 a,b 这两个数字//找到 tmp 中比特位为 1 的下标,代表 a 和 b 该下标的比特位不同int index=0;while(true){if(((tmp>>index)&1)==1){break;}index++;}//根据 index 下标的比特位进行分组,两个缺失的数字会被分开int[]ret=new int[2];for(int i=1;i<=length+2;i++){//异或所有 index 下标的比特位为 0 的数if(((i>>index)&1)==0){ret[0]^=i;}else{//异或所有 index 下标的比特位为 1 的数ret[1]^=i;}}for(int i=0;i<length;i++){if(((nums[i]>>index)&1)==0){ret[0]^=nums[i];}else{ret[1]^=nums[i];}}return ret;}
}
题解:
本题很明确,数组的内容应该是完整的从 1 ~ N 所有的整数,但现在缺了两个,本题通过位运算异或可以很巧妙的解决
首先需要了解异或的一些特性,a^0 = a, a^a = 0,简单来说异或的特性就是两个相同的数进行异或可以互相抵消
以示例2为例,nums = 2,3 ,所以完整的数据应该是 1 ~ nums.length+2 ,即 1,2,3,4 ,我们将完整的数据以及 nums 中的所有数据都进行异或,其中 2,3 都有两个可以互相抵消,所以最终得到的结果就是 1^4 ,也就是我们要找的那两个缺失的数,现在首要的问题就是如何将我们要找的这两个数分离出来
进行异或操作时,相同的比特位为 0 ,不同的比特位为 1 ,我们现在有的数据是 tmp = a^b(a,b 是要获取的缺失的数),既然想要分离 a,b 的话,就需要找 a,b 的不同之处,我们可以找出 tmp 比特位为 1 的下标,比特位为 1 就代表该下标 a 和 b 的比特位不同,将该下标比特位为 1 的数和比特位为 0 的数分开,这样 a 和 b 肯定就分开了
由于除了 a 和 b 两个数以外,其余的数都是有两个的可以互相抵消,所以将比特位为 1 的数和比特位为 0 的数分别进行异或,最后就能得到 a,b 的值