1.本题知识点
位运算,异或
2. 题目描述
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
3. 思路
这题考察的是异或操作,即对应位上值相同为0,值不同为1。
① 异或操作满足交换结合律,比如A ^ B ^ A = B ^ (A ^A) = B ^ 0 = B。所以,数组中数字两两异或,若其中有2个单次出现的数字,最后得到的结果就是这2个单次数字的异或结果,其他出现2次的数字都异或抵消掉了。
② 通过①的分析,假设数组中只有一个单次的数字,那么异或后的结果就是这个数,所以,考虑把原数组分开,通过什么分开呢?原数组异或结果位数为1的索引值,区分开2个单次的数,最后分别求2个子数组异或的结果即可。
举例说明:
![在这里插入图片描述](https://img.php1.cn/3cd4a/1e618/bdf/129913486c37ddf6.jpeg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTI0MTUwMzU=,size_16,color_FFFFFF,t_70)
③ 如何知道是哪个位上不同呢?比如上面是第n =3位不同,现在我们要找到这个n。
方法:通过【原数组异或结果】【从后往前找到第一个1】的位置即可。
举例:
![在这里插入图片描述](https://img.php1.cn/3cd4a/1eebe/cd5/0ef126b5295c089b.webp?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTI0MTUwMzU=,size_16,color_FFFFFF,t_70)
Java版本:
package com.algorithm.array;
public class NumXOR {public static void main(String[] args) {int [] array &#61; {2,4,3,6,3,2,5,5};int[] num1 &#61; new int[array.length];int[] num2 &#61; new int[array.length];findNumsAppearOnce(array, num1, num2);System.out.println(num1[0] &#43; " " &#43; num2[0]);}static void findNumsAppearOnce(int [] array,int num1[] , int num2[]){if(array &#61;&#61; null || array.length &#61;&#61; 0){num1[0] &#61; -1;num2[0] &#61; -1;}int bitResult &#61; 0;for(int i &#61;0 ; i < array.length; i&#43;&#43;){bitResult ^&#61; array[i];}int index &#61; findFirst1(bitResult);for(int i &#61;0 ; i < array.length; i&#43;&#43;){if(isBit1(array[i],index)){num1[0] ^&#61; array[i];}else{num2[0] ^&#61; array[i];}}}static int findFirst1(int bitResult){int index &#61; 0;while((bitResult & 1) &#61;&#61; 0){bitResult >>&#61; 1;index&#43;&#43;;}return index;}static boolean isBit1(int target, int index){return ((target >> index) & 1) &#61;&#61; 1;}
}