【LeetCode】190. 颠倒二进制位

leetcode

 

解题思路

颠倒二进制位需要将最高位与最低位交换,次高位与次低位交换,依此类推。有两种高效方法:

  1. ​​逐位循环法​​:每次循环取出最低位,放入结果的高位位置
  2. ​​分治交换法​​:通过位运算分组交换实现(16位交换、8位交换等),效率更高

关键步骤

方法1:逐位循环法

  1. ​​初始化结果变量​​:res = 0
  2. ​​循环32次​​:
    • 左移res腾出最低位
    • n的最低位加入res
    • 右移n处理下一位
  3. ​​返回结果​​:循环结束后res即为颠倒后的值

方法2:分治交换法(位运算优化)

  1. ​​交换16位分组​​:n = (n >> 16) | (n << 16)
  2. ​​交换8位分组​​:n = ((n & 0xff00ff00) >> 8) | ((n & 0x00ff00ff) << 8)
  3. ​​交换4位分组​​:n = ((n & 0xf0f0f0f0) >> 4) | ((n & 0x0f0f0f0f) << 4)
  4. ​​交换2位分组​​:n = ((n & 0xcccccccc) >> 2) | ((n & 0x33333333) << 2)
  5. ​​交换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位是固定大小

关键点

  1. ​​位运算技巧​​:

    • n & mask用于提取特定位
    • <<>>实现位的位置交换
    • |用于合并位段
  2. ​​Go特性​​:

    • 无符号整数右移高位补0(逻辑右移)
    • 32位整数保证位操作安全
  3. ​​性能对比​​:

    • 逐位法:直观易懂,适合教学和理解原理
    • 分治法:效率更高(5步完成),适合高性能场景
  4. ​​边界处理​​:

    • 全0和全1的特殊情况
    • 最高位和最低位的正确处理
    • 32位固定长度的循环保证完整性
  5. ​​实际应用​​:

    • 数据编码/解码
    • 图像处理中的像素反转
    • 密码学中的位操作变换
    • 网络协议中的字节序转换
posted @ 2025-06-12 18:30  云隙之间  阅读(32)  评论(0)    收藏  举报