leetcode-201_2021_10_17

leetcode-201_颠倒二进制位

法一:

经典做法,也是最简单的做法。创建一个新的对象ret来维护颠倒后的结果。遍历n的32位,如果第i位为1,那么ret的第(31-i)位为1。有一个小细节就是如果n的最高位的1已经被遍历,那么就可以提前结束,因为后面全是0。

class Solution {
     
public:
    uint32_t reverseBits(uint32_t n) {
     
        uint32_t ret = 0;
        for(int i = 0; i < 32; ++i){
     
            if(!(n >> i)) //优化,如果n >> i为0,那么无需再循环了
            break;

            if((n >> i) & 1){
     
                ret |= (1 << (31 - i)); 
            }
        }
        return ret;
    }
};

法二:

class Solution {
     
public:
    uint32_t reverseBits(uint32_t n) {
     
        n = ((n >> 16) & m1) + ((n << 16) & M1);
        n = ((n >> 8)  & m2) + ((n << 8)  & M2);
        n = ((n >> 4)  & m3) + ((n << 4)  & M3);
        n = ((n >> 2)  & m4) + ((n << 2)  & M4);
        n = ((n >> 1)  & m5) + ((n << 1)  & M5);
        return n;
    }
private:
    int m1 = 0xffff; // 0000 0000 0000 0000 1111 1111 1111 1111 
    int M1 = 0xffff0000;
    int m2 = 0xff00ff;
    int M2 = 0xff00ff00;
    int m3 = 0xf0f0f0f;
    int M3 = 0xf0f0f0f0;
    int m4 = 0x33333333;
    int M4 = 0xcccccccc;
    int m5 = 0x55555555;
    int M5 = 0xaaaaaaaa; 
};

法二是很巧的算法。颠倒一个数字,就是将前16位变成后16位,后16位变到前16位。然后在每个16位中,将前8位变成后8位,后8位变成前8位。然后在每8位中再次对半交换…直到交换的位变成1。我们利用掩码就很容易实现这个过程。

leetcode-201_2021_10_17_第1张图片
交换的过程需要掩码来实现,我们将n >> 16需要清除前16位的影响,所以需要&上
0000 0000 0000 0000 1111 1111 1111 1111,n << 16位同理,然后将二者相加就是交换了前16位和后16位。
将n >> 8位后,为了清除不必要位的影响,需要&上0000 0000 1111 1111 0000 0000 1111 1111,保留第1-8位和17-24位的数字,其他位清零。左移同理。然后将二者相加就交换了前8位和后8位。
下面的都是同理。

你可能感兴趣的:(leetcode,leetcode,算法)