1.在一个无序数组中有99个不重复的正整数,范围是1-100,唯独缺少一个整数,怎么找出这个整数。
最佳解法:
先算出1+2+++100的值,然后依次减去数组中的元素,的到最后的差值就是那个缺失的整数。
2.问题扩展:一个无序数组里面有若干个整数,范围还是1到100,其中99个整数出现偶数次,只有一个整数出现了奇数次,如何找个这个整数?
最佳解法:
遍历整个数组,依次做异或运算,由于疑惑运算在进行位运算的时候,相同为0,不同为1,因此所有出现偶次次的整数都会相互抵消为0,只有唯一出现奇次数的整数会被留下。
例如,给出一个无序数组{3,1,3,2,4,1,4}
做异或运算3 xor 1 xor 3 xor 2 xor 4 xor 1 xor 4 = 2
数组为n,时间复杂度为O(n),空间复杂度为O(1);
3.问题扩展:假设一个无序数组里有若干个正整数,范围还是1到100,其中有98个整数出现了偶数次,只有2个整数出现了奇数次,如何找到这两个出现奇数次的整数。
解法:把两个出现了奇数次的整数命名为A和B,遍历整个数组,然后依次做异或运算,进行异或运算的最终结果,等同于A和B进行异或运算的结果,在这个结果中,至少会有一个二进制是1,例如{4,1,2,2,5,1,4,3}的运算结果是00000110B。
然后,选定结果中值为1的某一位数字,这说明A和B对应的二进制的倒数第二位是不同的,因此可以将原数组按照二进制的倒数第二位的不同分为2组,一部分的倒数第二味是0,一部分的是1.这样就回到了上个问题。
代码如下
public class findLostNum {
public static int[] findLastNum(int[] array){
int result[] = new int[2];
//用于存储两个出现奇数次的整数
int xorResult = 0;
//第一次进行异或运算
for(int i=0;i<array.length;i++){
xorResult ^= array[i];
}
if(xorResult == 0){
return null;
}
//确定两个整数的不同位,以此分组
int separator = 1;
while (0==(xorResult&separator)){
separator <<=1;
}
for(int i=0;i<array.length;i++){
if(0 == (array[i] & separator)){
result[0] ^=array[i];
}else{
result[1]^=array[i];
}
}
return result;
}
public static void main(String[] args){
int[] array = {4,1,2,2,5,1,4,3};
int[] result = findLastNum(array);
System.out.println(result[0]+","+result[1]);
}
}