「位运算」的奇巧淫技

182 阅读2分钟

笔者最近再做算法题的时候,发现可以通过位运算 | 0 取整去替代parseInt()方法的使用,由此收录了一些位运算优化的使用场景。

位运算符表

image.png

1.取整

位运算符只将整数部分转化为二进制,遇到小数时,会自动将小数部分舍去。
以下三种位运算符都能够实现取整的需求,可以通过它们替代Math.floor()parseInt()

1.1 异或运算取整

    13.3 ^ 0 //13
    -13.3 ^ 0 //-13

1.2 或运算符取整

    12.2 | 0 // 12
    -12.2 | 0 // 12

1.3 双否运算取整

    ~~13.3 // 13
    ~~-13.3 // -13

1.4 左移运算取整

    12.2 << 0 // 12
    -12.2 << 0 // -12

2. 判断数组中是否存在某个值

    let arr = [5,7,9]
    if(~arr.indexOf(7)){//替代indexOf() > -1
        console.log('存在')
    }

3. 判断奇偶性

    if( n % 2) == 01
        // n 是个奇数
    }else{
        // n是偶数
    }

4. 交换两个数

异或^的性质:

  1. 交换律 可以任意交换运算因子的位置,结果不变
  2. 结合律(即(a^b)^c = a^(b^c)
  3. 对于任何数x,都有x^x = 0x^0 = x
  4. 自反性 A^B^B = A^0 =A
    //常规写法
    int tmp = x
    x = y
    y = tmp
    
    //通过异或替代辅助变量
    x = x ^ y   // 
    y = x ^ y   // y = (x ^ y) ^ y = x ^ y ^ y = x
    x = x ^ y   // x = (x ^ y) ^ x = x ^ x ^ y = y

5. 找出唯一成对的数

    // 1-1000这1000个数放在长度为1001的数组arr中,只有一个数重复出现,请把它找出来
    let x1 = 0
    for(let i = 0; i < arr.length; i++){
        x1 = x1 ^ i  // x1 = 1^2^3^...^1000
    }
    for(let i = 0; i < arr.length; i++){
        x1 = x1 ^ arr[i] // x1 = (1^2...^1000)^(1^2^...^k^k^...^1000) = 0^0^...^k = k
    }

总结

位运算的奇巧淫技能够在很多算法题中帮助我们更简单地解决问题,简化我们的代码量,提高做题速度!希望本文能够对你有所帮助。