Description:
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.
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 space complexity?
Example:
Given nums = [1, 2, 1, 3, 2, 5], return [3, 5].
Link:
https://leetcode.com/problems/single-number-iii/description/
解题方法:
这道题的难点在于数组中有两个distinct数,但是如果能将这个数组分开从而导致这两个也分开,那么就成了single number I 的问题。至于其他的数,因为两两相同,所以只要是以数的值(而不是数组的index)来分割的方法,其他的相同的数一定会分割在一起。
步骤 + 例子:
如上面给出的例子:Given nums = [1, 2, 1, 3, 2, 5].
1、我们先用异或求到xor值为6,此时只要找到xor值二进制的一个1,这个1代表了在这个位置上,两个数3(011), 5(101)是不同的。
2、然后,让一个变量firstOne
的值为(010):也就是在一步中找到的1的相同位置(第二个位置)为1,其他位置为0。
3、此时分析一下,两个数与firstOne
的关系必然是:其中一个 & firstOne == 0
和 另一个 & firstOne != 0
。而数组中其他数已经可以不用管了,反正一定会两两分在一边。
Tips:
==
的优先级高于&
所以像以下代码(diff & firstOne) == 0
前面要加括号。
Time Complexity:
O(N)
完整代码:
vector<int> singleNumber(vector<int>& nums)
{
if(nums.size() < 2)
return {};
int diff = 0;
for(int i: nums)
diff ^= i;
int firstOne = 1;
while((diff & firstOne) == 0)
firstOne <<= 1;
vector<int> result(2, 0);
for(int i: nums)
{
if((i & firstOne) == 0)
result[0] ^= i;
else
result[1] ^= i;
}
return result;
}