Vison's Blog
所有文章
文章总览
编辑器
Publications
About Me
Search
目录
#toc-container
下载Markdown文件
【3.29】LeetCode每日一题· 颠倒二进制位
2021年03月29日 9时11分
标签:
LeetCode
二进制
分治
## 题目描述 颠倒给定的 32 位无符号整数的二进制位。 #### 提示 请注意,在某些语言(如 Java)中,没有无符号整数类型。在这种情况下,输入和输出都将被指定为有符号整数类型,并且不应影响您的实现,因为无论整数是有符号的还是无符号的,其内部的二进制表示形式都是相同的。 在 Java 中,编译器使用[二进制补码](https://baike.baidu.com/item/%E8%A1%A5%E7%A0%81/6854613?fromtitle=%E4%BA%8C%E8%BF%9B%E5%88%B6%E8%A1%A5%E7%A0%81&fromid=5295284)记法来表示有符号整数。因此,在上面的**示例 2**中,输入表示有符号整数`-3`,输出表示有符号整数`-1073741825`。 #### 进阶 如果多次调用这个函数,你将如何优化你的算法? #### 示例1 ``` 输入: 00000010100101000001111010011100 输出: 00111001011110000010100101000000 解释: 输入的二进制串 00000010100101000001111010011100 表示无符号整数 43261596, 因此返回 964176192,其二进制表示形式为 00111001011110000010100101000000。 ``` #### 示例2 ``` 输入:11111111111111111111111111111101 输出:10111111111111111111111111111111 解释:输入的二进制串 11111111111111111111111111111101 表示无符号整数 4294967293, 因此返回 3221225471 其二进制表示形式为 10111111111111111111111111111111 。 ``` #### 提示 ``` 输入是一个长度为 32 的二进制字符串 ``` #### 来源 > 来源:力扣(LeetCode) > 链接:[题目链接](https://leetcode-cn.com/problems/reverse-bits "题目链接") ## 逐位反转 将十进制数的反转扩展到二进制数,每次取`n`的最后一位`n&1`,并将答案变量`res`左移一位,然后将其放到`res`的最后一位,`n`右移一位。重复以上操作32次(注意,不是直到`n`为0)。 Tips,当然也可以直接利用左移操作直接将`n&1`移到对应的位置上,这样就不用重复32次了。 ### 代码 ```cpp class Solution { public: uint32_t reverseBits(uint32_t n) { uint32_t res = 0, cnt = 0; while(cnt < 32){ res <<= 1; res |= (n&1); n >>=1; cnt++; } return res; } }; ``` ## 用时和内存 > 执行用时:0 ms,在所有 C++提交中击败了100.00%的用户 > 内存消耗:5.9 MB,在所有 C++提交中击败了29.57%的用户 ## 分治 除此以外,还可以利用分治法,将数字分为左16位和右16位,然后对于左16位和右16位,继续分成左8位和右8位……如此下去直到不能分割为止,然后分别交换分割出的两部分,最后就可以得到颠倒二进制位后的数字,如图(直接使用的LeetCode官方题解的图)  在这里由于固定了二进制为32位,因此可以从底向上实现。 具体地,利用位掩码和移位操作。例如对于第一次迭代(对应分治法递归的最后一层),需要将所有奇偶位互换,那么可以定义 ```cpp M1 = 0x55555555; // 0101 0101 0101 0101 ``` * 使用`n & M1`可以取出所有的奇数位,再左移一位即可将所有奇数位换到偶数位;即使用`(n & M1) << 1`可以取出所有的偶数位并将其换到奇数位; * 使用`(n >> 1) & M1`可以取出所有的偶数位并将其换到奇数位。 * 因此,使用`((n & M1) << 1) | ((n >> 1) & M1)`即可将奇偶位互换。 相似地,可以设计出分治法中另外层次的替换方法。 ### 代码 ```cpp class Solution { private: const uint32_t M1 = 0x55555555; //0b01010101010101010101010101010101; const uint32_t M2 = 0x33333333; //0b00110011001100110011001100110011; const uint32_t M4 = 0x0f0f0f0f; //0b00001111000011110000111100001111; const uint32_t M8 = 0x00ff00ff; //0b00000000111111110000000011111111; public: uint32_t reverseBits(uint32_t n) { n = ((n & M1) << 1) | ((n >> 1) & M1); n = ((n & M2) << 2) | ((n >> 2) & M2); n = ((n & M4) << 4) | ((n >> 4) & M4); n = ((n & M8) << 8) | ((n >> 8) & M8); return (n >> 16) | (n << 16); } }; ``` ## 用时和内存 > 执行用时:0 ms,在所有 C++提交中击败了100.00%的用户 > 内存消耗:5.7 MB,在所有 C++提交中击败了88.59%的用户
所有评论
暂无评论
新增评论
评论
邮箱
邮箱仅作验证使用
图形验证码
邮箱验证码
发送验证码
发表评论
所有评论
暂无评论