题目
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?
中文大意
给定一个数组nums,该数组中只有两个元素只出现一次,其他元素都是出现两次的,找出只出现一次的这两个元素。
分析
(1)在没有看到大神们的解答之前,我们一般会想到的常规方法就是使用Map类型,其中key为元素值,value为元素的个数,但是这样的效率很低,下面来看看大神的解法。
(2)主要分为两步:
a.将数组中的所有元素进行XOR运算,结果为res,XOR的特性是相同为0,相异为1,所以res实际为数组中那两个不相同的元素的异或结果,而这个res的二进制中某位值为“1”,也就意味着这两个元素的二进制对应位上的值是不同的;
b.虽然得到了两个不相同元素的异或结果,但是还没有将这两个元素彻底区分开,所以我们可以将所有的元素分为两组,而分组的标准(这个方法的核心重点)是:先使用res &= -res获得的res对应二进制中最右边的“1”的位置,即res &= -res操作完成后,会使res中在原res上最后一个“1”的位置上的值为1,而其他的全部为0。res再和nums数组中的所有元素进行“&”操作,nums[i] & res == 0 的为一组,其他情况为另一组,然后将两组数据分别进行异或运算,得到的就是两个所要求的元素。
java代码实现
class Solution {
public int[] singleNumber(int[] nums) {
int res = 0;
for(int i = 0; i < nums.length;i++){
res ^= nums[i];
}
res &= -res;
int[] ans = new int[2];
for(int j = 0;j<nums.length;j++){
if((res & nums[j]) == 0){
ans[0] ^= nums[j];
}else{
ans[1] ^= nums[j];
}
}
return ans;
}
}