import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param array int整型一维数组
* @return int整型一维数组
*/
// public int[] FindNumsAppearOnce (int[] array) {
// // write code here
// //找出重复数字呀,找出不重复的,最快的就是hash
// HashSet<Integer> set =new HashSet<>();
// int index= 0;
// for(index=0;index<array.length;index++){
// if(!set.add(array[index])){
// set.remove(array[index]);
// }
// }
// int[] result = new int[set.size()];
// index = 0;
// Iterator<Integer> iterator = set.iterator();
// while(iterator.hasNext()){
// result[index++]=iterator.next();
// }
// return result;
// }
//异或处理 相同数异或为0,0异或 1个数还是这个数 所有数直接异或就能找到唯一不重复的数了。
//寻找两个不重复的数
public int[] FindNumsAppearOnce (int[] array) {
int[] result= new int[2];
int m = 0;
for(int num :array){
m ^= num;
}
//找到两个数 不同的那一位
int x= 1;
while((m&x) == 0){
x<<=1;
}
for(int num :array){
//在x 这位 两个数不同,所以 这位与上x 为0的为一组,不为0 的 另一组
if((num & x) == 0){
result[0] ^=num;
}else{
result[1] ^=num;
}
}
if(result[0]>result[1]){
m = result[0];
result[0] = result[1];
result[1] = m;
}
return result;
}
}
本文给出两种方法
一个是哈希,时间复杂度o(n) 空间复杂度o(n)
一个是位运算的方法 时间复杂度o(n) 空间复杂度o(1)
位运算的逻辑就是利用异或的性质,只有 0 ^1 = 1 其他为0.所以相同数字 异或是0,不同数字异或是所有相同位置 不同数字 的值。
知道了这个性质,难点就在于如何区别开 两个都不重复的数字,怎么能够单独找到其中一个!!!
遍历一次数组,异或后得到一个数,这个数就是不重复的两个数异或出来的结果,这两个数字不同点就在于有一些位置的数字是不同的,已经通过 异或运算找到了这些位置,这些位置的数字就是1.
但是如何用数字表示呢?
可以通过与运算,其实就相当于比如 快速幂这种思想,求一个数 有几个1。每一位的数字都去& 1
如果结果是1,说明这个数的这一位就是1.否则就是0。 num&1 == 0,如果等于0,就把1向左移一位,去比较num数字的第二位,循环遍历num的每一位,直到找到num为1的那一位就是两个数不同的那一位。记为x, 第一位不同 x=1,第二位不同 x=10
在遍历一次array,先不去管重复的元素,如果 因为两个单独数字在x这一位,一个是0,一个是1,所以 数字& x==0 说明 是其中一个元素,否则是另一个。这样就可以把数组分成两组。各自运算,重复元素没有影响,因为元素重复的 &x ==0 的情况下,所有重复元素都在同一组中,异或后为0,消失不见