目录
1,题目
2,代码
1,逐位颠倒
8=00001011
循环过程:
最终结果:
3,学习与总结
1,<< 位运算符
1,题目
颠倒给定的 32 位无符号整数的二进制位。
2,代码
1,逐位颠倒
/**
* @param {number} n - a positive integer
* @return {number} - a positive integer
*/
var reverseBits = function(n) {
// 存储最终结果
let revRes = 0;
for(let i =0;i<32 && n> 0;i++){
revRes |= (n & 1)<< (31-i);
n >>>= 1;
}
return revRes >>> 0;
};
for (let i = 0; i < 32 && n > 0; ++i) {
- 这一行开始一个循环,从0迭代到31(包含),总共32次,对应
n
的32位。循环的另一个条件是n > 0
,这是为了优化性能,一旦n
变为0,就没有必要继续循环,因为剩下的位都是0。
rev |= (n & 1) << (31 - i);
- 在这一行,首先通过
n & 1
获取n
的最低位(即最右边的位),然后将这个位左移(31 - i)
位,将它放置到颠倒后的正确位置上。接着,使用位或操作|=
将这个位加到rev
上。这样,每一次循环都会将n
的一个位颠倒到rev
的对应位置上。
n >>>= 1;
- 这一行使用无符号右移操作符
>>>
将n
右移一位。这样做是为了在下一次循环中处理n
的下一个最低位。无符号右移确保了当n
被视为无符号整数时,高位补0。
return rev >>> 0;
- 最后一行返回颠倒位后的结果
rev
。这里使用>>> 0
是一个技巧,用于确保结果是一个32位无符号整数。在JavaScript中,即使变量已经是一个无符号整数,这种操作也可以保证结果正确无误地被视为无符号整数。
以8位二进制为例:
8=00001011
循环过程:
我们逐位遍历
n
,并将每一位移动到其颠倒后的位置。
第1次迭代(i = 0):
n & 1
得到n
的最低位,即1
。- 将这个位左移
(7 - 0)
位,得到10000000
。- 将
10000000
通过位或操作加到rev
上,rev
变为10000000
。- 将
n
右移一位,变为00000101
。第2次迭代(i = 1):
- 类似地,处理后
n
的最低位,得到1
,左移(7-1)得到1000000。
与之前的rev进行或运算,得到rev=11000000。
n
右移一位,变为00000010
。第3次迭代(i = 2):
- 处理
n
的最低位0
,rev不变。n
右移一位,变为00000001
。第4次迭代(i = 3):
- 处理
n
的最低位1
,左移得到(7-3)位,得到10000上。与之前的rev进行或运算,得到rev=11010000。
n右移一位,变为0000 0000。
- 第5次迭代(i = 4):
- n=0 循环终止
最终结果:
- 经过上述步骤后,我们得到
rev
为11010000
(以8位为例)。这是原始二进制位00001011
颠倒后的结果。
3,学习与总结
1,<<
位运算符
<<
是一个位运算符,在各种编程语言中都有定义,称为“左移位”运算符。它将数值的二进制表示向左移动指定的位数。
左移位运算符的规则和效果如下:
基本操作:对于表达式
a << b
,它的意思是将a
的二进制表示向左移动b
位。右边空出的位将用0填充。乘以2的效果:左移一位的效果等同于将数值乘以2。更具体地说,
a << b
等同于a
乘以2^b
(2的b次方)。这是因为二进制系统中每向左移动一位,就相当于该数值乘以2。溢出处理:当你对一个整数左移位时,最左边超出该类型所能表示范围的位将被丢弃,而新的空位(在右边)将用0填充。这可能导致正数变成负数(对于有符号整数),或者是简单地丢失高位数据,具体取决于使用的是有符号整数还是无符号整数。
实例:如果我们有一个整数
2
,其二进制表示为10
,那么2 << 1
的结果将是4
,二进制表示为100
。相同地,2 << 2
的结果将是8
,二进制表示为1000
。
位运算分治 第二次再学习吧。
昨天忙于开会,没有做题!
告诫自己:贵在坚持,越是第一次接触,越不要贪快!