leetcode
解题思路
颠倒二进制位需要将最高位与最低位交换,次高位与次低位交换,依此类推。有两种高效方法:
- 逐位循环法:每次循环取出最低位,放入结果的高位位置
- 分治交换法:通过位运算分组交换实现(16位交换、8位交换等),效率更高
关键步骤
方法1:逐位循环法
- 初始化结果变量:
res = 0
- 循环32次:
- 左移
res腾出最低位
- 取
n的最低位加入res
- 右移
n处理下一位
- 返回结果:循环结束后
res即为颠倒后的值
方法2:分治交换法(位运算优化)
- 交换16位分组:
n = (n >> 16) | (n << 16)
- 交换8位分组:
n = ((n & 0xff00ff00) >> 8) | ((n & 0x00ff00ff) << 8)
- 交换4位分组:
n = ((n & 0xf0f0f0f0) >> 4) | ((n & 0x0f0f0f0f) << 4)
- 交换2位分组:
n = ((n & 0xcccccccc) >> 2) | ((n & 0x33333333) << 2)
- 交换1位分组:
n = ((n & 0xaaaaaaaa) >> 1) | ((n & 0x55555555) << 1)
代码实现
// 方法1:逐位循环法
func reverseBitsLoop(n uint32) uint32 {
var res uint32
for i := 0; i < 32; i++ {
res = (res << 1) | (n & 1) // 左移结果并添加最低位
n >>= 1 // 移除已处理的最低位
}
return res
}
// 方法2:分治交换法
func reverseBitsDivide(n uint32) uint32 {
// 交换32位中的高16位和低16位
n = (n >> 16) | (n << 16)
// 交换每16位中的高8位和低8位
n = ((n & 0xff00ff00) >> 8) | ((n & 0x00ff00ff) << 8)
// 交换每8位中的高4位和低4位
n = ((n & 0xf0f0f0f0) >> 4) | ((n & 0x0f0f0f0f) << 4)
// 交换每4位中的高2位和低2位
n = ((n & 0xcccccccc) >> 2) | ((n & 0x33333333) << 2)
// 交换每2位中的高1位和低1位
n = ((n & 0xaaaaaaaa) >> 1) | ((n & 0x55555555) << 1)
return n
}
示例测试
func main() {
testCases := []struct {
input uint32
expect uint32
}{
{0b00000010100101000001111010011100, 964176192}, // 示例1
{0b11111111111111111111111111111101, 3221225471}, // 示例2
{0b10000000000000000000000000000000, 1}, // 边界测试1
{0xFFFFFFFF, 0xFFFFFFFF}, // 全1测试
}
fmt.Println("测试结果:")
for _, tc := range testCases {
res1 := reverseBitsLoop(tc.input)
res2 := reverseBitsDivide(tc.input)
fmt.Printf("输入: %032b\n", tc.input)
fmt.Printf("逐位法: %032b (%d)\n", res1, res1)
fmt.Printf("分治法: %032b (%d)\n", res2, res2)
fmt.Printf("预期值: %d\n", tc.expect)
fmt.Println("匹配:", res1 == tc.expect && res2 == tc.expect, "\n")
}
}
复杂度分析
| 方法 | 时间复杂度 | 空间复杂度 | 循环/操作次数 |
| 逐位循环法 |
O(1) |
O(1) |
32次循环 |
| 分治交换法 |
O(1) |
O(1) |
5次位运算 |
注:两种方法都是常数时间复杂度,因为32位是固定大小
关键点
-
位运算技巧:
n & mask用于提取特定位
<<和>>实现位的位置交换
|用于合并位段
-
Go特性:
- 无符号整数右移高位补0(逻辑右移)
- 32位整数保证位操作安全
-
性能对比:
- 逐位法:直观易懂,适合教学和理解原理
- 分治法:效率更高(5步完成),适合高性能场景
-
边界处理:
- 全0和全1的特殊情况
- 最高位和最低位的正确处理
- 32位固定长度的循环保证完整性
-
实际应用:
- 数据编码/解码
- 图像处理中的像素反转
- 密码学中的位操作变换
- 网络协议中的字节序转换