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?
.
开始时候用的HashSet很烦,而且在我还没把这个方法完整好的时候,就已经受不了了,于是又没忍住偷看了眼大牛的代码
看完之后,真是觉得自己不适合编程···
public class Solution {
public int[] singleNumber(int[] nums) {
int diff = 0;
for (int num : nums) {
diff ^= num;
}
// Get its last set bit
diff &= -diff;
// Pass 2 :
int[] rets = {0, 0}; // this array stores the two numbers we will return
for (int num : nums)
{
if ((num & diff) == 0) // the bit is not set
{
rets[0] ^= num;
}
else // the bit is set
{
rets[1] ^= num;
}
}
return rets;
}
}
这是一个十分可怕的思路,也不知道是怎么想出来的,膜拜之
首先把所有的数两两异或,这样最后得到的结果,一定是那两个single number的异或后的结果,代码中记为diff,这个diff中只要有一个bit位为1
这意味着什么呢?
意味着这两个single number在这个bit位上是不一致的!这意味着他们这个bit位肯定一个是0,一个是1!由此可以通过这个bit位来区分两个single number!
于是这个数组可以通过这个特征位分成两组,两组中的数为{single_number1,x,x···} {single_number2,y,y,z,z···}不需要去管里面有多少个
每一组元素两两异或之后得到的就是那两个single_number,因为异或——相同为0嘛!
所以这题的关键就落在了,如何寻找这个特征位呢???
这里就用了 diff&=-diff
这个式子求出了diff中最靠末尾的而且是“1”的那个比特位,为什么呢?
这就涉及负数在内存中是补码存在的,补码是啥?负数的补码就是,真值部分按位取反,末尾+1。
这就很容易理解为什么 diff&=-diff可以取得最靠末尾的1,例:6=0000 0110 6&-6=0000 0110&1111 1010=0000 0010
这题就完美结束了!
貌似至今为止,没有一道题是自己做出来的···真是蠢!