一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。
题目链接: 数组中只出现一次的两个数字
示例 1:
输入:nums = [4,1,4,6]
输出:[1,6] 或 [6,1]
示例 2:
输入:nums = [1,2,10,4,1,4,3,3]
输出:[2,10] 或 [10,2]
任何数和本身异或则为0,任何数和 0 异或是本身。
我们依旧从头到尾异或每个数字,那么最终的结果就是这两个只出现一次的数字的异或结果,由于两个数不同,因此这个结果数字中一定有一位为1, 把结果中第一个1的位置记为第n位。因为是两个只出现一次的数字的异或结果,所以这两个数字在第n位上的数字一定是1和0。接下来我们根据数组中每个数字的第n位上的数字是否为1来进行分组,恰好能将数组分为两个都只有一个数字只出现一次的数组,对两个数组从头到尾异或,就可以得到这两个数了。
public int[] singleNumbers1(int[] nums) {
int xor=0;
//将数组全部进行异或,异或的结果就是两个值出现一次的数字的异或结果
for (int num : nums) {
xor^=num;
}
//寻找上一步中异或结果在最末尾开始计算第一次出现一个位数,例如上一位的结果是0110 ,这一步找到的就是2
int s=1;
while ((xor&s)==0){
s<<=1;
}
//对原数组进行分组并异或
//在原数组中两个数在第n位上必定为0或者1
int[] res=new int[2];
for (int num : nums) {
if((num&s)==0){
res[0]^=num;
}else{
res[1]^=num;
}
}
return res;
}