位运算

119 阅读2分钟

位运算符

  1. 与&:遇0则0
  2. 或 |:遇1则1
  3. 异或 ^ :相同为0,相异为1.
  4. 左移<<:左移一位,相当于原数乘2;左移n位,原数乘2^n
  5. 右移>>:右移一位,相当于原数除2;右移n位,原数除2^n
  6. 取反运算符:参加运算的一个数据,按二进制进行“取反”运算。

与运算的用途

  1. 判断奇偶 只要根据最未位是0还是1来决定,为0就是偶数,为1就是奇数。因此可以用if ((a & 1) == 0)代替if (a % 2 == 0)来判断a是不是偶数

或运算的用途

常用来对一个数据的某些位设置为1

异或运算的用途

  1. 与0相异或值不变,1010 1110 ^ 0000 0000 = 1010 1110
  2. 交换两个数,

image.png

相关算法题目

第一题

image.png

答案1
var countBits = function(n) {
    let arr = []
    function getNumberOf1(number) {
        let res = 0
        while (number != 0) {
          res++
          number &= (number - 1)
        }
        return res
      }
    for(let i = 0; i <= n; i++) {
        arr.push(getNumberOf1(i))
    }
    return arr
};


number-1:一个数-1就把该数得二进制最右边的1后面的这部分取反操作,如6的二进制0110,减一后的二进制为0101

number&(number-1):进行与操作之后就可以把该数最右边的1消掉,0110 & 0101 = 0100,这样就把0110右边的1消除掉了.

依次循环处理,当number=0的时候也就意味着这个数的所有1都被消除了,res的数据消除了几个1,就代表这个数据有几个1

答案2
var countBits = function(n) {
    let arr = []
    function getNumberOf1(number) {
        let flag = 1
        let res = 0
        while (flag != 0) {
            if ((number & flag) != 0) {
                res++
            }
            flag = flag << 1
        }
        return res
    }
    for(let i = 0; i <= n; i++) {
        arr.push(getNumberOf1(i))
    }
    return arr
};

number & flag:当flag=1时,一个数与1做与运算结果不是0,则意味这个二进制数最末尾的一定是1,如6的二进制01100110 & 1 = 0000,最末尾不是1

依次循环,flag << 1左移也就是flag变成了100110 & 10 = 0010,不是0,代表有存在1

这个算法逻辑是利用与运算规则,从最右边开始计算出现1的个数,所以flag是需要向左移动,同时flag一直左移直到为0
答案3
var countBits = function(n) {
    let arr = []
    function getNumberOf1(number) {
        let res = 0
        while (number != 0) {
            number = number - (number & -number)
            res++
        }
        return res
    }
    for(let i = 0; i <= n; i++) {
        arr.push(getNumberOf1(i))
    }
    return arr
};


-number:比如x= 10101010,-x =~x+1 = 01010101+1 = 01010110 ,也就是-x与x的区别就是最右保留,后面的全部与源数据相反,

number & -number:number[10101010],number[01010110],两数相与也就是消除了最左侧的1

依次循环即可得出1的个数