知识点:任意一个数字跟他本身异或得到的都是0;
对于一个数组中如果只有一个数字只出现一次,那么这个数组最后异或得到的结果就是它;问题中有两个只出现一次的数字:
解决过程:
- 数组异或得到的结果为两个只出现一次的数字异或得到
- 找到这个结果第一个出现1的位置
- 按照得到的位置上是否为1将数组分成两个:含有若干对数字和一个只出现一次的数字
最后对两个数组中的数字异或,得到的就是两个只出现一次的
如何得到数字的第一位为1的位置:
与1异或,并右移
如何判断某个数的某位上是否为1:
右移xx位,与1异或是否为0
代码:
package core;
/**问题描述:一个整形数组中只有两个数字只出现一次,其他数字出现两次。找出这两个数字
* 输入:{2,6,6,3,2,4,5,5,4,7}
* 输出:3,7
* Created by lxq on 2017/9/14.
*/
public class Problem4 {
public static void main(String[] args){
Problem4 problem4 = new Problem4();
int[] array = {2,4,3,6,3,4,5,6};
problem4.findNumbersAppearOnce(array);
}
public void findNumbersAppearOnce(int[] array){
if(array==null)
return;
int number = 0;//整个数组异或结果,两个只出现一次数字异或得到的结果
for(int i:array)
number ^=i;
int index = findFirstBitIsOne(number);
int number1 = 0; //第一个子数组异或得到结果
int number2 = 0; //第二个子数组异或得到结果
//按照 index位上是否是1来分成两个数组:
// 这样分,出现两次的数字分到一个子数组中,
//两个只出现一次的数字被分别分到两个数组中去
for(int i:array){
if(isBitOne(i,index)){
number1 ^=i;
}else {
number2 ^=i;
}
}
System.out.println(number1);
System.out.println(number2);
}
//对于异或结果找到第一个位上数字为1的位置
private int findFirstBitIsOne(int number) {
int indexBit = 0;
while ((number&1)==0){
//右移
number = number>>1;
++indexBit;
}
return indexBit;
}
//数字的index位上是否为1
//右移index位
private boolean isBitOne(int number, int index) {
number = number>>index;
return (number&1)==0;
}
}