力扣刷题Days15第二题-137. 只出现一次的数字 II(js)

文章讲述了在给定整数数组中,通过使用哈希表和位移运算符(左移、有符号右移、无符号右移)实现线性时间复杂度的算法,找出只出现一次的元素。作者详细解释了代码中的逻辑,并介绍了位移运算符在性能优化和类型转换中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1,题目

2,代码

2.1哈希表

2.2 依次确定每一个二进制位

3,学习与总结

1. 左移运算符 (<<)

2. 有符号右移运算符 (>>)

3. 无符号右移运算符 (>>>)


1,题目

给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。

你必须设计并实现线性时间复杂度的算法且使用常数级空间来解决此问题。

2,代码

2.1哈希表

/**
 * @param {number[]} nums
 * @return {number}
 */
var singleNumber = function(nums) {
    // 哈希表
    const hashtable = new Map();
    for(let num of nums){
        hashtable.set(num,(hashtable.has(num)|| 0) + 1);
    }
    for(let [key,value] of hashtable){
        if(value===1){
            return key;
        }
    }

};

下次注意使用迭代器

for( const [num, occ] of freq.entries() )

2.2 依次确定每一个二进制位

/**
 * @param {number[]} nums
 * @return {number}
 */
var singleNumber = function(nums) {
    // 依次确定每一个二进制位
    let ans = 0;
    for(let i=0;i<32;i++){
        let total =0;
        for(let num of nums){
            total += (num >> i) & 1;
        }
        if(total%3 != 0){
            ans |= (1 << i);
        }

    }
    return ans;
    
};
((num >> i) & 1)

num 的第 i 位移动到最低位,检查这一位是否为 1

ans |= (1 << i) 

ans |= (1 << i) 的作用是将 ans 的第 i 位设置为 1。这是通过创建一个只在第 i 位为 1 的数字(即 1 << i),然后将其与 ans 进行按位或操作来实现的。如果 ans 在第 i 位原本就是 1,这个操作保持该位为 1;如果 ans 在第 i 位是 0,这个操作将其修改为 1

假设 ans 当前的值是 2(二进制 0010),我们要将第 2 位(从右向左数,从 0 开始计数)设置为 1

  • 1 << 2 生成了一个在第 2 位为 1 的数字,即 0100(二进制)或 4(十进制)。
  • 接着,ans |= (1 << 2) 相当于 0010 | 0100,结果是 0110(二进制),即 6(十进制)。
for (let i = 0; i < 32; ++i) { ... }:外层循环遍历从 0 到 31 的整数 i,代表要检查的二进制位的位置。这是因为 JavaScript 中的数字是以 32 位整数形式存储的。

3,学习与总结

JavaScript 中有几种位移运算符

1. 左移运算符 (<<)

  • 语法x << n
  • 作用:将 x 的二进制表示向左移动 n 位,右边空出的位用 0 填充。
  • 示例4 << 1 的结果是 8,因为 4 的二进制是 100,向左移一位变成 1000,即 8

2. 有符号右移运算符 (>>)

  • 语法x >> n
  • 作用:将 x 的二进制表示向右移动 n 位,保持符号位不变(即正数左边填充 0,负数填充 1)。
  • 示例-8 >> 2 的结果是 -2-8 的二进制表示(假设是 8 位)是 11111000,向右移两位,填充最左边的符号位(1),得到 11111110,即 -2

3. 无符号右移运算符 (>>>)

  • 语法x >>> n
  • 作用:将 x 的二进制表示向右移动 n 位,左边空出的位用 0 填充,不考虑符号位。
  • 示例-8 >>> 2 的结果取决于你的 JavaScript 引擎如何处理 32 位整数,但它会将 -8 视为一个很大的正数(因为二进制的最高位被视为值位而不是符号位)。

使用场景和注意事项:

  • 性能优化:位移运算符通常用于性能敏感的低层代码,例如图形计算、加密算法等,因为它们直接操作二进制位,运行速度快。
  • 逻辑操作:位移运算可以用来执行乘法或除法操作(例如,左移一位相当于乘以 2,右移一位相当于除以 2),但要注意符号和数值范围。
  • 无符号右移:在处理无符号数或将负数以无符号的形式解释时特别有用。
  • 类型转换:位移运算符会将操作数转换为 32 位整数,这可能会导致意外的行为,尤其是在使用无符号右移时。

示例

假设 num = 5(二进制为 0101)和 i = 2,我们来看这行代码如何工作:

  • 首先,num >> i5 >> 2,意味着将 5 的二进制表示向右移动两位,得到 0001
  • 接着,(num >> i) & 10001 & 0001,结果为 1,因为最低位是 1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值