190 颠倒二进制位
颠倒给定的 32 位无符号整数的二进制位。
提示:
请注意,在某些语言(如 Java)中,没有无符号整数类型。在这种情况下,输入和输出都将被指定为有符号整数类型,并且不应影响您的实现,因为无论整数是有符号的还是无符号的,其内部的二进制表示形式都是相同的。
在 Java 中,编译器使用二进制补码记法来表示有符号整数。因此,在 示例 2 中,输入表示有符号整数 -3
,输出表示有符号整数 -1073741825
。
方法
每次取最后一位,然后移动,直到整个数颠倒。
public class Solution {
// you need treat n as an unsigned value
public int reverseBits(int n) {
int res = 0;
for (int i = 0; i < 31; ++i){
int bottom = n & 1;
n = n >> 1;
res = res | bottom;
res = res << 1;
}
if (n < 0) res = res | 1;
return res;
}
}
方法二 二进制掩码
考虑将一个二位整数ab
颠倒,引入二进制掩码01
。交换的过程如下:
- 将
ab
右移,得到0a
- 将
01
与ab
做与操作,得到0b
,然后将0b
左移,得到b0
- 最后将
b0
和0a
做或操作,得到颠倒后的整数ba
。
如果整数的长度不是2
,那么将其一直分半,每次将分半后的两部分数字颠倒,直到整个数被分成若干个长度为2
的部分,则回到了最初的情况。这种方法的本质是分治思想。
public class Solution {
// you need treat n as an unsigned value
public int reverseBits(int n) {
int swap1 = 0x0000FFFF;
int swap2 = 0x00FF00FF;
int swap3 = 0x0F0F0F0F;
int swap4 = 0x33333333;
int swap5 = 0x55555555;
n = ((n >>> 16) & swap1) | ((n & swap1) << 16);//交换前16位和后16位
n = ((n >>> 8) & swap2) | ((n & swap2) << 8);//交换相邻的4位
n = ((n >>> 4) & swap3) | ((n & swap3) << 4);
n = ((n >>> 2) & swap4) | ((n & swap4) << 2);
n = ((n >>> 1) & swap5) | ((n & swap5) << 1);
return n;
}
}
今日另做了136、191、231,由于题目简单,在此不做记录。