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.

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 space complexity?

题意:给定一个数组,包含出现两次和一次的元素,其中只有两个元素只出现一次;现要求找出这只出现了一次的两个元素;

解法:对于数组中只包含一个出现一次的元素,我们可以对所有的元素进行异或操作,那么最后得到的结果就是只出现一次的那个元素;
对于数组中包含两个出现一次的元素来说,我们可以将其划分为两个部分,每个部分都只包含一个出现一次的元素,这样我们分别对这两个部分的所有元素进行异或操作后就可以得到这两个只出现了一次的元素;所以,现在的问题就是如何就是如何将这个数组划分为两个两个部分;
我们知道如果异或的结果为1,那么这两个数的二进制表示中肯定有一个位置上一个为1,另外一个为0;我们就可以找到这个位置,根据这个位置上数字是1还是0将整个数组划分为两个部分,之后再分别对这两个部分进行异或操作就能够得到两个只出现一次的元素;

Java
class Solution
public int[] singleNumber(int[] nums) {
//用于存储数组中所有数的异或结果
int xorResult = 0;
for (int num : nums) {
xorResult ^= num;
}
//获得二进制表示中出现的第一个1的位置
int firstIndex = firstIndexIsOne(xorResult);
//定义只出现了一次的两个元素
int result1 = 0;
int result2 = 0;
for (int num : nums) {
if (indexPositonIsOne(num, firstIndex)) result1 ^= num;
else result2 ^= num;
}
return new int[] {result1, result2};
}

//判断数字的二进制表示中index位是否为1
private boolean indexPositonIsOne(int num, int index) {
return ((num >> index) & 0x1) == 1 ? true : false;
}

//从数字的二进制表示中的低位向高位找到第一个为1的位置
private int firstIndexIsOne(int num) {
int index = 0;
while (index < 32 && (num & 0x1) == 0) {
index++;
num >>= 1;
}
return index;
}
}