题目链接
136. 只出现一次的数字
题目描述
自己没做出来,看别人的题解 T_T
分析:
- 凡是重复的元素都只出现两次。
方法一:位运算
链接:官方题解
异或运算的性质:
性质1 任何数和 0 0 0 做异或运算,结果仍然是原来的数,即 a ⊕ 0 = a a \oplus 0=a a⊕0=a 。
性质2 任何数和其自身做异或运算,结果是 0 0 0 ,即 a ⊕ a = 0 a \oplus a=0 a⊕a=0 。
性质3 异或运算满足交换律和结合律,即 a ⊕ b ⊕ a = a ⊕ a ⊕ b = ( a ⊕ a ) ⊕ b = 0 ⊕ b = b a \oplus b \oplus a = a \oplus a \oplus b = (a \oplus a)\oplus b = 0 \oplus b = b a⊕b⊕a=a⊕a⊕b=(a⊕a)⊕b=0⊕b=b 。
.
假设数组中有 2 m + 1 2m+1 2m+1 个数,其中有 m m m 个数各出现两次, 1 1 1 个数出现一次。令 a 1 、 a 2 、 … 、 a m a_{1} 、a_{2}、\ldots、a_{m} a1、a2、…、am 为出现两次的 m m m 个数, a m + 1 a_{m+1} am+1 为出现一次的数。根据性质 3,数组中的全部元素的异或运算结果总是可以写成如下形式:
( a 1 ⊕ a 1 ) ⊕ ( a 2 ⊕ a 2 ) ⊕ … ⊕ ( a m ⊕ a m ) ⊕ a m + 1 (a_{1} \oplus a_{1}) \oplus (a_{2} \oplus a_{2})\oplus \ldots \oplus (a_{m} \oplus a_{m})\oplus a_{m+1} (a1⊕a1)⊕(a2⊕a2)⊕…⊕(am⊕am)⊕am+1
根据性质1和性质2,可以化简为:
0 ⊕ 0 ⊕ … ⊕ 0 ⊕ a m + 1 0 \oplus 0 \oplus \ldots \oplus 0 \oplus a_{m+1} 0⊕0⊕…⊕0⊕am+1
因此异或运算的结果是数组中只出现一次的数字。
/**
* @param {number[]} nums
* @return {number}
*/
var singleNumber = function(nums) {
xor=0;
for(let i=0;i<nums.length;i++){
xor^=nums[i]; // '^' 异或运算
}
return xor;
};
复杂度分析:
- 时间复杂度: O ( N ) O(N) O(N) ,其中 N 是数组的长度。只需要遍历一次数组。
- 空间复杂度: O ( 1 ) O(1) O(1)。
方法二:哈希表
- 设计一个哈希表用来存储只出现一次的数字;
- 遍历一次数组,如果元素在hash表中(即该数字出现两次),则删除该数字;
- 最后剩下的就是只出现一次的数字。
/**
* @param {number[]} nums
* @return {number}
*/
var singleNumber = function(nums) {
const set = new Set();
for(let i=0;i<nums.length;i++){
if(set.has(nums[i])){
set.delete(nums[i]);
continue;
}
else set.add(nums[i]);
}
return([...set]); //...(展开操作符)操作符将Set转换为Array
};
复杂度分析:
- 时间复杂度: O ( N ) O(N) O(N) ,其中 N 是数组的长度,遍历一次数组。
- 空间复杂度: O ( N ) O(N) O(N) ,N 是数组的长度,主要是哈希表的开销。【不符合题意】