1. 程式人生 > 其它 >【位運算】力扣190:顛倒二進位制位

【位運算】力扣190:顛倒二進位制位

顛倒給定的 32 位無符號整數的二進位制位。
提示:
請注意,在某些語言(如 Java)中,沒有無符號整數型別。在這種情況下,輸入和輸出都將被指定為有符號整數型別,並且不應影響您的實現,因為無論整數是有符號的還是無符號的,其內部的二進位制表示形式都是相同的。
在 Java 中,編譯器使用二進位制補碼記法來表示有符號整數。因此,在 示例 2 中,輸入表示有符號整數 -3,輸出表示有符號整數 -1073741825。
示例:

輸入:n = 00000010100101000001111010011100
輸出:964176192 (00111001011110000010100101000000)
解釋:輸入的二進位制串 00000010100101000001111010011100 表示無符號整數 43261596,因此返回 964176192,其二進位制表示形式為 00111001011110000010100101000000。

方法1:
使用算術左移和右移,可以很輕易地實現二進位制的翻轉:每次把 res 左移,把 n 的二進位制末尾數字,拼接到結果 res 的末尾。然後把 n 右移。

class Solution:
    def reverseBits(self, n: int) -> int:
        res = 0
        for i in range(32):
            # res = (res << 1) | (n & 1)
            res = res << 1
            res += n & 1 
            n >>= 1
        return res

時間複雜度:O(1)。
空間複雜度:O(1)。

方法2:分治法
有另外一種不使用迴圈的做法,類似於歸併排序。
其思想是分而治之,把數字分為兩半,然後交換這兩半的順序;然後把前後兩個半段都再分成兩半,交換內部順序……直至最後交換順序的時候,交換的數字只有 1 位。
也就是:
32位無符號整數,如 1111 1111 1111 1111 1111 1111 1111 1111
表示成16進位制 f f f f f f f f
一個16進位制的f代表二進位制的4位
ffff ffff右移16位,變成 0000 ffff
ffff ffff左移16位,變成 ffff 0000
它們倆【相或】,就可以完成低16位與高16位的交換;
之後的每次分治,都要先【與】上一個掩碼,再進行交換。

class Solution:
    # @param n, an integer
    # @return an integer
    def reverseBits(self, n):
        n = (n >> 16) | (n << 16) # 低16位與高16位交換
        n = ((n & 0xff00ff00) >> 8) | ((n & 0x00ff00ff) << 8) # 每16位中低8位和高8位交換;1111是f
        n = ((n & 0xf0f0f0f0) >> 4) | ((n & 0x0f0f0f0f) << 4) # 每8位中低4位和高4位交換
        n = ((n & 0xcccccccc) >> 2) | ((n & 0x33333333) << 2) # 每4位中低2位和高2位交換;1100是c,0011是3
        n = ((n & 0xaaaaaaaa) >> 1) | ((n & 0x55555555) << 1) # 每2位中低1位和高1位交換;1010是a,0101是5
        return n

作者:fuxuemingzhu
連結:https://leetcode.cn/problems/reverse-bits/solution/fu-xue-ming-zhu-xun-huan-yu-fen-zhi-jie-hoakf/

時間複雜度:O(1)
空間複雜度:O(1)