两种解题方式
1、蒙混过关方法
定义若干长度数组,存储出现次数,最后遍历即可
class Solution {
public int[] findNumsAppearOnce(int[] nums) {
int[] n = new int[10000];
for(int i = 0;i<nums.length;i++){
n[nums[i]]++;
}
int ii=0;
int[] res = new int[2];
for(int i = 0;i<n.length;i++){
if(n[i]==1){
res[ii]=i;
ii++;
}
}
return res;
}
}
时间复杂度$O(n)$,牺牲较大空间
2、异或运算、位运算方法
class Solution {
public int[] findNumsAppearOnce(int[] nums) {
/* 假设两个唯一的数为x和y,先把所有的数异或一遍,可以得到x ^ y */
/*
任意数字n^n=0,不同数字^后保留不同部分
Because:数据中只有两个数字x、y出现一次,出现两次及以上的部分异或结束为0,只剩下出现一次的两个数结果x^y
*/
int xy = 0;
for(int num : nums){
xy ^= num;
}
/* 再找到x ^ y中某一位为1,则x和y在这一位上一定不同(一个是1一个是0) */
/*
>> : 各二进位全部右移若干位,高位补0
<< : 各二进位全部左移若干位,低位补0
找到x与y不同(0、1)的第一位,通过此位,可以将遍历x^y结果把x和y区分出来
*/
int k = 0;
while((xy >> k & 1) == 0) k++;
/*
通过此位将原来所有的数分成两类:此位是1和此位是0(此时x和y各属于一类)
在每一类中找出唯一的那个数
*/
int x = 0;
for(int num : nums)
if((num >> k & 1) == 1)
x ^= num;
int y = x ^ xy;
int[] res = new int[]{x, y};
return res;
}
}