位运算chapter4:掩码法---位分治原地逆置二进制表达式

class Solution {
public:
    uint32_t reverseBits(uint32_t n) {
    n = (n & 0xaaaaaaaa) >> 1 | (n & 0x55555555) << 1;
    n = (n & 0xcccccccc) >> 2 | (n & 0x33333333) << 2;
    n = (n & 0xf0f0f0f0) >> 4 | (n & 0x0f0f0f0f) << 4;
    n = (n & 0xff00ff00) >> 8 | (n & 0x00ff00ff) << 8;
    n = n >> 16 | n << 16;
    return n;
}
};

这个函数旨在将32位无符号整数 n 的比特位进行翻转。下面是各个步骤的详细说明:

  1. 交换所有相邻的比特位

    n = (n & 0xaaaaaaaa) >> 1 | (n & 0x55555555) << 1;
    

    在这一步,我们想要交换每一对相邻的比特位。0xaaaaaaaa 是一个掩码,它在32位表示中,其二进制形式为 10101010 10101010 10101010 10101010,它选中原整数中的所有奇数位 (1-based)。0x55555555 是另一个掩码,它在32位表示中为 01010101 01010101 01010101 01010101,它选中原整数中的所有偶数位。

    当我们执行 (n & 0xaaaaaaaa) >> 1,我们实际上是将所有奇数位向右移动1位,填充到偶数位的位置;当我们执行 (n & 0x55555555) << 1,我们将所有偶数位向左移动1位,填充到奇数位的位置。这样,原整数中所有相邻的位就被交换了。

  2. 交换每2位内的比特位

    n = (n & 0xcccccccc) >> 2 | ((n & 0x33333333) << 2);
    

    这一步中,我们交换每隔1位的比特位,也就是说,我们现在操作每一对位中的每4个位。类似的,0xcccccccc 是一个掩码,二进制表示为 11001100 11001100 11001100 11001100,它选中每4个位的高两位,而 0x33333333 是 00110011 00110011 00110011 00110011,它选中每4个位的低两位。

    当我们右移 n & 0xcccccccc 之后,我们将原整数中每组4位内的前2位移动到原来后2位的位置;同理,左移 n & 0x33333333,将每组4位内的后2位移动到原来前2位的位置,从而实现位的交换。

  3. 交换每4位内的比特位

    n = (n & 0xf0f0f0f0) >> 4 | (n & 0x0f0f0f0f) << 4;
    

    在这里,我们转而交换每隔3位的比特位,即我们操作每8位内的比特位。掩码 0xf0f0f0f0 二进制表示为 11110000 11110000 11110000 11110000,它选中每组8位中的前4位;0x0f0f0f0f 为 00001111 00001111 00001111 00001111,它选中每组8位中的后4位。

    执行这个步骤之后,每组8位中的前4位和后4位会相互交换位置。

  4. 交换每8位内的比特位

    n = (n & 0xff00ff00) >> 8 | (n & 0x00ff00ff) << 8;
    

    现在,我们将一组16位中的比特位进行翻转。使用掩码 0xff00ff00,二进制表示为 11111111 00000000 11111111 00000000,选择每组16位中的前8位;0x00ff00ff 是 00000000 11111111 00000000 11111111,它选中每组16位中的后8位。

    这一步将每组16位中前8位与后8位交换位置。

  5. 交换16位块

    n = n >> 16 | n << 16;
    

    这是最终步骤,在这里,我们做一个16位的块交换。这里没有掩码,因为我们直接做一次16位的大交换:将原数的前16位移动到后16位的位置,将后16位移动到前16位的位置。

组合这些步骤,我们逐渐扩大了交换比特位的间隔距离,从最原始的相邻位一直到16位块,实现了一个完整的32位二进制数的位翻转。

时间复杂度O\log \log n

  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值