用分治法加速反转二进制位

目录

题目描述

基本思路

优化思路

代码实现


题目描述

给定一个32位无符号数,将其从最高位反转至最低位,最低为反转至最高位,如abcd,反转为dcba

基本思路

开辟一个临时变量,循环将待反转数的最低位取出,放置在临时变量的最高位;次低位放置在临时变量的次高位,依次执行,时间复杂度位O(32)

uint32_t reverseBits(uint32_t n) {
    uint32_t r = 0;                   // 临时变量
    for(int i=0; i<32; i++){
        int bit = n & (1 << i);       //取低位
        if(bit) {
            r  = r | (1 << (31-i));   // 放置在高位
        }           
    }
    return r;
}

优化思路

利用分治的思想,考虑字符abcd,我们反转的过程,可以是这样的:将abcd对半开,将ab放在cd的位置,将cd放在ab的位置;然后依次反转ab和cd;也就是反复划分子串并反转子串,直至递归的最终情况,只剩2个字符,将这两个字符反转即可

对于一个32位的无符号数,需要进行5次交换:2个16位的子串、4个8位的子串、8个4位的子串、16个2位的子串、以及最后的两两交换。从上到下交换和从下到上的交换结果是一样的,因此我们可以先两两交换

利用掩码可以实现快速交换,例如两两交换:我们可以左移1位将原来偶数位的交换至奇数位,右移一位将原来奇数位的交换至偶数位;利用掩码的逻辑与运算将非需要的位置0,再利用掩码的逻辑或运算将两个交换的半串拼接

假设我们要交换无符号数n,掩码可以设置为010101010101010101010101010101,代码可以这样写:

uint32_t mask1 = 0x55555555;    // 设置掩码
n1 = ((n >> 1) & mask1)         // 右移将偶数位移至奇数位,掩码消除偶数位
n2 = ((n & mask1) << 1);        // 掩码消除偶数位,左移将奇数位移至偶数位
n = n1 | n2;                    // 逻辑或运算将奇数位与偶数位合并

当然也可以写简洁一点:

 n = ((n >> 1) & mask1) | ((n & mask1) << 1);

对于交换2位子串、4位子串等,也是类似的思路,只是左右移的位数和掩码有所区别;具体的可以看代码实现

代码实现

uint32_t reverseBits(uint32_t n) {
    // 掩码
    uint32_t mask1 = 0x55555555;    // 01010101010101010101010101010101
    uint32_t mask2 = 0x33333333;    // 00110011001100110011001100110011
    uint32_t mask4 = 0x0f0f0f0f;    // 00001111000011110000111100001111
    uint32_t mask8 = 0x00ff00ff;    // 00000000111111110000000011111111

    // 依次交换
    n = ((n >> 1) & mask1) | ((n & mask1) << 1);
    n = ((n >> 2) & mask2) | ((n & mask2) << 2);
    n = ((n >> 4) & mask4) | ((n & mask4) << 4);
    n = ((n >> 8) & mask8) | ((n & mask8) << 8);
    n = (n >> 16) | (n << 16);

    return n;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值