【LeetCode】136. 只出现一次的数字(位运算/哈希表)

题目链接
136. 只出现一次的数字

题目描述

自己没做出来,看别人的题解 T_T

分析:

  • 凡是重复的元素都只出现两次。

方法一:位运算

链接:官方题解

异或运算的性质:

性质1 任何数和 0 0 0 做异或运算,结果仍然是原来的数,即 a ⊕ 0 = a a \oplus 0=a a0=a
性质2 任何数和其自身做异或运算,结果是 0 0 0 ,即 a ⊕ a = 0 a \oplus a=0 aa=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 aba=aab=(aa)b=0b=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} a1a2am 为出现两次的 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} (a1a1)(a2a2)(amam)am+1
根据性质1和性质2,可以化简为:
0 ⊕ 0 ⊕ … ⊕ 0 ⊕ a m + 1 0 \oplus 0 \oplus \ldots \oplus 0 \oplus a_{m+1} 000am+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 是数组的长度,主要是哈希表的开销。【不符合题意】
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值