View on GitHub wznonstop

只出现一次的数字

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

示例:

输入: [4,1,2,1,2]
输出: 4

实现:

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {void} Do not return anything, modify nums in-place instead.
 */
var singleNumber = function(nums) {
    if (nums.length < 2) {
        return nums[0];
    }
    nums.sort((a,b)=>(a-b));
    let single = null;
    nums.reduce(function(pre,cur,index,nums){
        if (index === 1) {
            if ((nums[index-1] - cur) !== 0) {
                single = nums[index-1];
            }
        } else if (index < (nums.length - 1)) {
            if ((nums[index-1] - cur) * (nums[index+1] - cur) !== 0) {
                single = cur;
            }
        } else {
            if (cur - (nums[index - 1]) !== 0) {
                single = cur;
            }
        }
    });
    return single;
};

我一看,用了100多ms,只超过了62.62%,于是点开了用时几十ms的解答,开启了懵的大门。。。

var singleNumber = function(nums) {
  let result = 0;
  nums.forEach(el => (result ^= el));
  return result;
};

看了好几个,全都是使用 ^ 来解答的,看不懂,搜了一圈,知道 ^ 是位运算 XOR,二进制表示下,当只有一个数位存放的是 1 时,它才返回 1。 那又怎么样呢,把每个数都转成二进制?❓❓❓ 脑子完全被二进制的疑惑给塞满了,4 ^ 1 = 5, 5 ^ 2 = 7, 7 ^ 2 = 5, ❓❓❓ 实在是很懵了,就跑去问大佬了,大佬给我解释了一通,我开始还是没转过弯,后来突然明白了! 因为对正整数n来说,n ^ n = 0, 0 ^ n = n,为什么是这样的呢?

 25 = 0000 0000 0000 0000 0000 0000 0001 1001
  3 = 0000 0000 0000 0000 0000 0000 0000 0011
 ---------------------------------------------
XOR = 0000 0000 0000 0000 0000 0000 0001 1010

位运算 XOR,二进制表示下,当只有一个数位存放的是 1 时,它才返回 1,不论n转为二进制之后是什么, n ^ n 每一位的操作数都是相同的,因此结果的每一位都会是0,最终结果也是0,类似的道理,可以得出 0 ^ n = n 的结论。

nums.forEach(el => (result ^= el)); ,就是将数组中的每一个元素连着进行XOR操作, 不论顺序如何,两个相同的数XOR运算的最终结果都是0,最终留下的就是那个只出现一次的数字了。

被这个骚操作彻底折服!