这里用由于我们的数里面有两个数不同,相同的都化为0了,那么不同的肯定有地方不是0的,我们就根据不为0的那个数进划分,分为两组,一组包含一个单独的数。
在分组之后:我们对分组之后的所有的数进行异或处理,得到结果就是唯一的一个不重复的数,也就是num^0的结果还是num
/****************************************************************************************
*题目:数组中只出现一次的数字
* 一个整型的数组里除了2个数字外,其他的数字都出现了2次。请写程序找出这两个只出现一次的数字。时间复杂度是O(n),空间复杂度是O(1)
*
* 解题思路:利用异或,数异或自己为0
*时间:2015年10月4日10:39:59
*文件:NumbersAppearOnce.java
*作者:cutter_point
****************************************************************************************/
package bishi.Offer50.y2015.m10.d04;
import org.junit.Test;
public class NumbersAppearOnce
{
//找出这个数的二进制的第一个1是第几位
private int findFirstBitIs1(int num)
{
int indexBit = 0;
//第一个条件是为了判断,最右是0还是1,如果不是1,那么就继续循环
//然后是避免索引越界
while(((num & 1) == 0) && (indexBit < 32))
{
num = num >> 1; //右移1位
++indexBit;
}//while
return indexBit;
}
/**
* 判断num的右边开始第indexBit位是不是1
* @param num
* @param indexBit
*/
private boolean isBit1(int num, int indexBit)
{
num = num >> indexBit;
boolean result = false;
if((num & 1) == 1)
{
result = true;
}//if
else
{
result = false;
}//else
return result;
}
public void findNumsAppearOnce(int data[], int num1[], int num2[])
{
if(data == null || data.length < 2)
return;
int resultExclusiveOR = 0;
//对所有的数进行异或
for(int i = 0; i < data.length; ++i)
{
resultExclusiveOR ^= data[i];
}//for
//求出我们所有的值异或之后的结果
//由于是只有两个数是不一样的,所以我们把这两个数分为两个组,第一个位置为1的地方异或,肯定是那个位的值不同
int indexOf1 = findFirstBitIs1(resultExclusiveOR);
num1[0] = num2[0] = 0;
for(int j = 0; j < data.length; ++j)
{
if(isBit1(data[j], indexOf1))
{
//如果indexOf1是哪一位的话
num1[0] ^= data[j];
}//if
else
{
num2[0] ^= data[j];
}//else
}//for
}
@Test
public void Test()
{
NumbersAppearOnce n = new NumbersAppearOnce();
int data[] = {2,4,3,6,3,2,5,5};
int num1[] = {0}, num2[] = {0};
n.findNumsAppearOnce(data, num1, num2);
System.out.println(num1[0] + " 和 " + num2[0]);
}
}