题目:
Given an array of numbers nums, in which exactly two elements appear
only once and all the other elements appear exactly twice. Find the
two elements that appear only once.Example:
Input: [1,2,1,3,2,5] Output: [3,5] Note: The order of the result is not important. So in the above example, [5,3] is also correct. Your algorithm should run in linear runtime complexity.
Could you implement it using only constant spacecomplexity?
解释:
数组中仅有两个元素出现过一次,剩下的元素都出现两次,请找到这两个仅仅出现一次的数。
假设需要找的两个数字是A和B
1.
对数组进行一遍异或,最终得到的是A^B
2.
因为A和B不同,所以A^B
的二进制必定在某些位为’1’(相同的两个数异或之后为0,异或:相同为0不同为1)
3.
取A^B
中结果为1的一位设置为1,其他位设置为0,不妨取从右边数的第一个’1’(例如,A^B
的结果为100110100,那么3
操作以后变为000000100),设A^B
=a,可以用a&=-a
完成这样的操作(a&=-a完成的操作是保留a的二进制中最低位的1,其余变成0
),对于a中为1的这一位,A和B在这一位必定一个是1,一个是0(因为相同为0,不同为1,异或结果为1证明A和B在这一位一个为1一个为0)
4.
数字 A 和 数字 B 中必然有一个数字与上 a为 0(a是经过操作的,即000000100,A,B中必然有一个数字在这一位是1,那么与上a就是0 了,因为a的其他位都是0,不妨假设与上a为0的数字是A);而我们在 a 中将其他位都设置为 0,那么该位为 0 的数字与上 a 就等于 0,而该位为 1 的数字与上 a 就等于a
5.
我们只需要再循环一次数组,将与上 a 为 0 的数字们进行 XOR 运算(A在这一组里),与上 a不为 0 的数字们(那么B在这一组中)进行独立的 XOR 运算。那么最后我们得到的这两个数字就是 A 和 B
python代码:
class Solution(object):
def singleNumber(self, nums):
"""
:type nums: List[int]
:rtype: List[int]
"""
a=reduce(lambda x,y:x^y,nums)
a&=-a
result=[0]*2
for num in nums:
if a&num==0:
result[0]^=num
else:
result[1]^=num
return result
c++代码:
class Solution {
public:
vector<int> singleNumber(vector<int>& nums) {
int a =0;
for (auto num:nums)
{
a^=num;
}
//a=A^B
int A=0,B=0;
//获取a的最低非0位 -a就是a取反+1
a&=-a;
for (int num:nums)
{
if (num&a)
{
A^=num;
}
else
{
B^=num;
}
}
vector<int> result={A,B};
return result;
}
};
总结:
a&(-a)
用于求a的最低非0位,-a
就是a
取反+1,a&(a-1)
用于判断a是否是2的幂,要记住这些常用操作。