难度:中等
一个整型数组 nums
里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是 O ( n ) O(n) O(n),空间复杂度是 O ( 1 ) O(1) O(1)。
输入:nums = [4,1,4,6]
输出:[1,6] 或 [6,1]
输入:nums = [1,2,10,4,1,4,3,3]
输出:[2,10] 或 [10,2]
限制:
基础知识必知:一篇文章搞懂位运算!!!
两个相等的元素 异或 的结果为 0,而 0 与任意数 x
异或 的结果都为 x
。
对本题给的数组的所有元素执行异或操作,得到的是两个不存在重复的元素异或的结果。例如对于数组 [x,x,y,y,z,k]
,x^x^y^y^z^k = 0^y^y^z^k = y^y^z^k = 0^z^k = z^k
。
两个不相等的元素在位级表示上一定会有所不同,因此这两个元素异或得到的结果 diff
一定不为 0:
ans[0] = diff
先保存这两个数的结果;diff
&
-diff
能得到 diff
位级表示中 最右侧为 1 的位,令 diff = diff & -diff
。diff
作为区分两个元素的依据,一定有一个元素对 diff
进行 与 运算的结果为 diff
,另一个结果为 0。设不相等的两个元素分别为 x
和 y
,遍历数组所有元素,判断每一个元素与 diff
的 与 结果是否为 diff
:
x
进行 异或 并赋值给 ans[1]
;x
异或操作,而且这些相等的元素异或的结果为 0,因此最后 只剩下 x
与 0 异或的结果;y = ans[0] ^ x
。C++
class Solution {
public:
vector<int> singleNumbers(vector<int>& nums) {
vector<int> ans(2);
int diff = 0;
for(int num : nums){//得到只出现一次的两个数的异或
diff ^= num;
}
ans[0] = diff; //记录两个数的异或结果
diff &= -diff; //得到最后一位1
for(int num : nums){//得到其中一个数
if((num & diff) == diff){
ans[1] ^= num;
}
}
ans[0] ^= ans[1];//得到另一个数
return ans;
}
};
Java
class Solution {
public int[] singleNumbers(int[] nums) {
int[] ans = new int[2];
int diff = 0;
for(int num : nums){//得到只出现一次的两个数的异或
diff ^= num;
}
ans[0] = diff; //记录两个数的异或结果
diff &= -diff; //得到最后一位1
for(int num : nums){//得到其中一个数
if((num & diff) == diff){
ans[1] ^= num;
}
}
ans[0] ^= ans[1];//得到另一个数
return ans;
}
}
题目来源:力扣。
放弃一件事很容易,每天能坚持一件事一定很酷,一起每日一题吧!
关注我LeetCode主页 / CSDN—力扣专栏,每日更新!