方法一 使用 map 额外空间
var singleNumber = function (nums) {
// 申请一个额外空间
let obj = {}
//遍历数组
nums.forEach((item) => {
//如果当前值在空间中找不到
if (obj[item] == undefined) {
//记录当前值出现的次数
obj[item] = 1
} else {
// 再次出现的删除
delete obj[item]
}
})
//将数据从额外空间提取出来
let result = Object.keys(obj).map((v) => Number(v))
return result
console.log(obj)
}
方法二 异或
利用相同异或为 0 思路;将数组所有数据异或如果设两个只出现一次的数假设为 x1,x2;
显而易见,x 与数组所有元素异或,一定有 x = x1 ^ x2;
剩下的就比较关键了;已知 x = x1 ^ x2 怎么找出 x1,x2 呢?
首先知道的条件,x != 0 ;因为如果 x == 0;则 x1 == x2;
首先,既然 x1 !== x2;那必然后 x1 的二进制与 x2 的二进制在某一位上不同;(这个条件是重点!!!!!!,理解这句话这题就明白了);
二进制嘛,特征明显,非 0 即 1;
假设 x1 的二进制与 x2 的二进制再第 k 为不相同;那是不是第 k 位一定有一个是 0;而另一个是 1;
由以上的表述,将数组数据分为两类,一类 k 位置为 0;一类 k 位置为 1;奇妙的事情发生了;因为除了 x1,x2 外数组其他数据两两相等,那么,俩俩相等的数据一定会被分配到同一个类型中;
同一类型中相同的数据会被抵消,抵消之后一类剩余 x1,而另一类必然剩余 x2;
哈哈,是不是很熟悉,第 136 题的代码是不是出现在了眼前;
参考代码如下
var singleNumber = function (nums) {
let x = 0
nums.forEach((e) => {
x = x ^ e
})
let x1 = 0
let x2 = 0
const k = x & -x
nums.forEach((e) => {
if (e & k) {
x1 = x1 ^ e
} else {
x2 = x2 ^ e
}
})
return [x1, x2]
}