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.
For example:
Given nums = [1, 2, 1, 3, 2, 5]
, return [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 space complexity?
思路:本题联系Single Number那题很容易想到将这组数据分成两个部分,每一个部分中各含有一个只出现一次的数,这样利用Single Number中的方法将这两个数找出来就行。本题的焦点就转移到了如何划分这个数组能达到这个要求上了。除了只出现一次的两个数外,其余的数字异或的结果是0.
两个只出现一次的数字A和B,AxorB=C;C的二进制数中为1的那一位在A和B中肯定是不同的。比如3xor5=011xor101=110;只需要根据这一位为0还是为1就可保证将这两个单独出现的数字划分在不同的部分中。
用到一个公式n&(~(n-1))可以得到n的最后一个1的掩码。根据这个掩码就可以将他们分成两部分。
这个掩码就跟网络通信中的子网掩码一个作用。
代码如下(已通过leetcode)
public class Solution {
public int[] singleNumber(int[] nums) {
int[] ans=new int[2];
int temp=0;
for(int i=0;i<nums.length;i++){
temp^=nums[i];
}
int mask=temp&(~(temp-1));
int A=0;
int B=0;
for(int i=0;i<nums.length;i++){
if((mask&nums[i])==0) A^=nums[i];
else B^=nums[i];
}
ans[0]=A;
ans[1]=B;
return ans;
}
}
public int[] singleNumber(int[] nums) {
int[] ans=new int[2];
int temp=0;
for(int i=0;i<nums.length;i++){
temp^=nums[i];
}
int mask=temp&(~(temp-1));
int A=0;
int B=0;
for(int i=0;i<nums.length;i++){
if((mask&nums[i])==0) A^=nums[i];
else B^=nums[i];
}
ans[0]=A;
ans[1]=B;
return ans;
}
}