• leetcode-190-Reverse Bits


    题目描述:

    Reverse bits of a given 32 bits unsigned integer.

    For example, given input 43261596 (represented in binary as 00000010100101000001111010011100), return 964176192 (represented in binary as 00111001011110000010100101000000).

    Follow up:
    If this function is called many times, how would you optimize it?

     

    要完成的函数:

    uint32_t reverseBits(uint32_t n)

     

    说明:

    1、给定一个32位的无符号型整数,转化为二进制,二进制反转,再输出对应的十进制。

    2、传统方法是:模仿人类思维,十进制转化为二进制,然后用栈反转输出,最后二进制再转化为十进制输出。可以完成本道题目,但是太麻烦了。

    3、在计算机中,数值本身就是用二进制存储的,所以我们可以用位操作得到每一位的值,然后“或”到反转之后对应的位上面去,最后直接输出就是十进制了。

       我们这样子做,避免了十进制转化为二进制的浪费时间的操作;避免了用栈,直接“或”到uint32_t类型的数字对应的位上;最后返回的这个数字就是我们要的十进制了。

          经历了前面几道题的洗礼, 现在可以说是十分喜欢位操作了呢,感觉十分简洁。

    代码:(笔者本人代码,实测6ms,beats 62.28% of cpp submissions)

    uint32_t reverseBits(uint32_t n) 
    {
        uint32_t b=1;//要“与”的数值
        uint32_t c;//存放“与”完的数值
        uint32_t d=0;//最终结果,uint32_t类型
        int index=32;
        for(int i=1;i<=16;i++)//处理后面的十六位
        {
            c=n&b;//取出每一位的值
            d|=(c<<(index-i));//把值放到相应的位上
            b<<=1;
            index--;
        }
        for(int i=17;i<=32;i++)//此时index=16,处理前面的十六位
        {
            c=n&b;
            d|=(c>>(i-index));
            b<<=1;
            index--;
        }
        return d;
    }

    时间复杂度是O(n),比起传统的方法快得不是一丁半点,避免了很多不必要的操作。

    但是在discuss区,又看到了大神的更加简洁的做法,跟大家分享一下。

    uint32_t reverseBits(uint32_t n) 
    {
        uint32_t m = 0;
        for (int i = 0; i < 32; i++, n >>= 1)
        {
            m <<= 1;
            m |= n & 1;
        }
        return m;
    }

    这样做更加简洁,代码更好写。但其实原理都是一样的,只不过笔者自己的代码中使用了更多的变量,变量也有一些操作,浪费了一点时间。而大神的代码比较巧妙,使用了类似十进制数字翻转的方法,数字不断x10往前挪。

    实测5ms,beats 86.90% 0f cpp submissions。

    本代码来源于leetcode用户@xcv58。侵删。

    在discuss区还看到了时间复杂度为O(logn)的做法,觉得有点厉害哈哈。分享给大家。

    uint32_t reverseBits(uint32_t n) 
    {
            n = (n >> 16) | (n << 16);//第一次变换
            n = ((n & 0xff00ff00) >> 8) | ((n & 0x00ff00ff) << 8);//第二次变换。注意把数字写成二进制形式要在前面加上“0x”
            n = ((n & 0xf0f0f0f0) >> 4) | ((n & 0x0f0f0f0f) << 4);//第三次变换
            n = ((n & 0xcccccccc) >> 2) | ((n & 0x33333333) << 2);//第四次变换
            n = ((n & 0xaaaaaaaa) >> 1) | ((n & 0x55555555) << 1);//第五次变换
            return n;
    }

    其实逻辑是这样的:

    以四个二进制数字作为一个单位,初始化为abcdefgh

    经过第一次变换,成为efghabcd

    经过第二次变换,成为ghefcdab

    经过第三次变换,成为hgfedcba

    接着对四个二进制数字内部做反转变化,假设四个数字为abcd

    经过第四次变换,成为cdab

    经过第五次变换,成为dcba

    至此,32位数值全部反转完成。

    实测5ms,beats 86.90% 0f cpp submissions。

    本代码来源于leetcode用户@tworuler。侵删。

  • 相关阅读:
    内存 : CL设置
    联通积分兑换的Q币怎么兑换到QQ上
    DB2数据库表追加字段
    显示菜单项与按钮项的关联关系
    如何将Windows8系统的磁盘格式(GPT格式)转换成Windows 7系统的磁盘格式(MBR格式)
    索尼(SONY) SVE1512S7C 把WIN8降成WIN7图文教程
    SqlServer之数据库三大范式
    Python并发编程-Redis
    Python并发编程-Memcached (分布式内存对象缓存系统)
    Python并发编程-RabbitMQ消息队列
  • 原文地址:https://www.cnblogs.com/chenjx85/p/8807707.html
Copyright © 2020-2023  润新知