切換
舊版
前往
大廳
主題

LeetCode - 190. Reverse Bits 解題心得

Not In My Back Yard | 2020-09-04 00:00:40 | 巴幣 0 | 人氣 1010

題目連結:


題目意譯:
反轉給定的 32 位元無號整數(Unsigned Integer)之位元。

注:
注意,某些程式語言像是 Java,並沒有所謂的無號整數型態。在這樣的狀況下,輸入及輸出都會是有號整數,而且應當不會影響你的實作,因為無論將給定字串視作有號或無號皆是同樣的表示法。
在 Java 中,編譯器使用 2 補數來表示有號整數。因此,在範例 2 中,輸入代表有號整數 -3 而輸出則是有號整數 -1073741825。

進階:
如果此函式會被呼叫許多次,你會怎麼最佳化它呢?

限制:
輸入長度 = 32 。



範例測資:
範例 1:
輸入: 00000010100101000001111010011100
輸出: 00111001011110000010100101000000
解釋: 輸入的二元字串 00000010100101000001111010011100 代表著無號整數 43261596 ,所以回傳 964176192 的二進位表示法 00111001011110000010100101000000。

範例 2:
輸入: 11111111111111111111111111111101
輸出: 10111111111111111111111111111111
解釋: 輸入的二元字串 11111111111111111111111111111101 代表著無號整數 4294967293 ,所以回傳 3221225471 的二進位表示法 10111111111111111111111111111111。



解題思維:
先觀察最基本的狀況,也就是只有兩個位元 ab,並令 n = ab。
ab 要變成 ba ,可以用左移「<<」以及右移「>>」運算子並搭配著「或」(Or)運算子,即「|」達成。如下:
(n >> 1) | (n << 1)
其中 >> 以及 << 在將一個位元移出邊界時,會從另一端補進一個「0」的位元。

那麼四個位元呢?
(n >> 2) | (n << 2) 只讓我們將 n = abcd 變成了 n = cdab,前兩個位元與後兩個交換了位置。

而我們只需要將 n 切一半分為左右邊,左右邊就變成了兩個位元的情況直接套該解法即可。而我們可以用位元遮罩(Bit Mask)達成,其操作需要「和」運算子,也就是「&」:
((n & 1000) >> 1) | ((n & 0100) << 1) | ((n & 0010) >> 1) | ((n & 0001) << 1)
如此一來 n 就變成了 dcba,即是所求。

而且可以看到,我們能將上式的右移、左移的部分合併成:
((n & 1010) >> 1) | ((n & 0101) << 1)

同理,八個位元、十六個位元等等也是類似上面的作法。利用位元遮罩以及分治法(Divide And Conquer)將各個部分一一地翻轉。




此次分享到此為止,如有任何更加簡潔的想法或是有說明不清楚之地方,也煩請各位大大撥冗討論。

創作回應

更多創作