题目:

image.png
image.png


个人解答:

我本来思路是利用字符串来进行颠倒,但该函数参数是uint_32不是字符串,因此这种问题应当对字符串直接处理。


官方解答:

方法一:逐位颠倒

思路:

将 nn 视作一个长为 3232 的二进制串,从低位往高位枚举 nn 的每一位,将其倒序添加到翻转结果 (简单)190.颠倒二进制位 - 图3 中。

代码实现中,每枚举一位就将 nn 右移一位,这样当前 nn 的最低位就是我们要枚举的比特位。当 nn 为 00 时即可结束循环。

需要注意的是,在某些语言(如 (简单)190.颠倒二进制位 - 图4)中,没有无符号整数类型,因此对 nn 的右移操作应使用逻辑右移。

代码:

  1. class Solution {
  2. public:
  3. uint32_t reverseBits(uint32_t n) {
  4. uint32_t rev = 0;
  5. for (int i = 0; i < 32 && n > 0; ++i) {
  6. rev |= (n & 1) << (31 - i);
  7. n >>= 1;
  8. }
  9. return rev;
  10. }
  11. };

image.png


方法二:位运算分治

思路

若要翻转一个二进制串,可以将其均分成左右两部分,对每部分递归执行翻转操作,然后将左半部分拼在右半部分的后面,即完成了翻转。

由于左右两部分的计算方式是相似的,利用位掩码和位移运算,我们可以自底向上地完成这一分治流程。
image.png

代码:

class Solution {
private:
    const uint32_t M1 = 0x55555555; // 01010101010101010101010101010101
    const uint32_t M2 = 0x33333333; // 00110011001100110011001100110011
    const uint32_t M4 = 0x0f0f0f0f; // 00001111000011110000111100001111
    const uint32_t M8 = 0x00ff00ff; // 00000000111111110000000011111111

public:
    uint32_t reverseBits(uint32_t n) {
        n = n >> 1 & M1 | (n & M1) << 1;
        n = n >> 2 & M2 | (n & M2) << 2;
        n = n >> 4 & M4 | (n & M4) << 4;
        n = n >> 8 & M8 | (n & M8) << 8;
        return n >> 16 | n << 16;
    }
};

image.png