给定一个非空整数数组,除了某个元素只出现一次之外,其他每一个元素均出现两次。找出那个只出现了一次的元素。算法
说明:数组
你的算法应该具备线性时间复杂度。 你能够不使用额外空间来实现吗?ui
示例 1:spa
输入: [2,2,1]
输出: 1
复制代码
示例 2:code
输入: [4,1,2,1,2]
输出: 4
复制代码
这道题目最简单的思路,是利用Hash查询的时间复杂度为O(1), 避免使用双层for循环,致使时间复杂度变为O(n^2)。可是这不是咱们今天关注的重点。内存
由于,这两天我一直在看位运算符的相关内容, 其实本题能够在不使用额外的内存空间,而且是O(n)的时间复杂度下,解答出该题。只须要使用按位异或的操做符^get
按位异或^, 本质上将两个操做数的二进制数的每一位对齐。而后按以下的规则取值,1 ^ 1 等于 0; 1 ^ 0 等于 1;0 ^ 1 等于1;0 ^ 0等于0。hash
举一个例子🌰。10和5之间进行按位异或操做的结果15。io
0000 0000 0000 0000 0000 0000 0000 1010
// ^ XOR
0000 0000 0000 0000 0000 0000 0000 0101
// 等于 14=5s
0000 0000 0000 0000 0000 0000 0000 1111
复制代码
✨除此以外,咱们还须要知道两个准则:for循环
// 0
100 ^ 100
// 0
-99 ^ -99
// 100
100 ^ 0
// -2
0 ^ -2
复制代码
/** * @param {number[]} nums * @return {number} */
var singleNumber = function(nums) {
let hashMap = new Map()
let result
for (let i = 0; i < nums.length; i++) {
if (!hashMap.has(nums[i])) {
hashMap.set(nums[i], 1)
} else {
hashMap.set(nums[i], 2)
}
}
for (let i = 0; i < nums.length; i++) {
if (hashMap.get(nums[i]) === 1) {
result = nums[i]
break
}
}
return result
};
复制代码
没错,就是这么简单😂
/** * @param {number[]} nums * @return {number} */
var singleNumber = function(nums) {
let result = 0
for (let i = 0; i < nums.length; i++) {
result = nums[i] ^ result
}
return result
};
复制代码
🤔️ 为何能够这样?原题中说给定一个非空整数数组,除了某个元素只出现一次之外,其他每一个元素均出现两次。找出那个只出现了一次的元素。
, 因而咱们能够将代码执行的过程分解成下面的过程
nums = [a, b, a, c, b, c, d]
result = a ^ b ^ a ^ c ^ b ^ c ^ d
result = (a ^ a) ^ (b ^ b) ^ (c ^ c) ^ d
result = 0 ^ 0 ^ 0 ^ d
result = d 获得了只出现了一次的数字