位运算符
- 与&:遇0则0
- 或 |:遇1则1
- 异或 ^ :相同为0,相异为1.
- 左移<<:左移一位,相当于原数乘2;左移n位,原数乘2^n
- 右移>>:右移一位,相当于原数除2;右移n位,原数除2^n
- 取反运算符:参加运算的一个数据,按二进制进行“取反”运算。
与运算的用途
- 判断奇偶 只要根据最未位是0还是1来决定,为0就是偶数,为1就是奇数。因此可以用if ((a & 1) == 0)代替if (a % 2 == 0)来判断a是不是偶数
或运算的用途
常用来对一个数据的某些位设置为1
异或运算的用途
- 与0相异或值不变,1010 1110 ^ 0000 0000 = 1010 1110
- 交换两个数,
相关算法题目
第一题
答案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的二进制0110,0110 & 1 = 0000,最末尾不是1
依次循环,flag << 1左移也就是flag变成了10,0110 & 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的个数