1. 程式人生 > 其它 >231. 2 的冪

231. 2 的冪

一個數 \(n\)\(2\) 的冪,當且僅當 \(n\) 是正整數,並且 \(n\) 的二進位制表示中僅包含 1 個 1。

因此我們可以考慮使用位運算,將 \(n\) 的二進位制表示中最低位的那個 \(1\) 提取出來,再判斷剩餘的數值是否為 \(0\) 即可。下面介紹兩種常見的與「二進位制表示中最低位」相關的位運算技巧。

第一個技巧是

\[\texttt{n & (n - 1)} \]

其中 \(\texttt{&}\) 表示按位與運算。該位運算技巧可以直接將 \(n\) 二進位制表示的最低位 \(1\) 移除,它的原理如下:

假設 \(n\) 的二進位制表示為 \((a 10\cdots 0)_2\)

,其中 \(a\) 表示若干個高位,1 表示最低位的那個 1,\(0\cdots 0\) 表示後面的若干個 \(0\),那麼 \(n-1\) 的二進位制表示為:

\[(a 01\cdots1)_2 \]

我們將 \((a 10\cdots 0)_2\)\((a 01\cdots1)_2\) 進行按位與運算,高位 \(a\) 不變,在這之後的所有位都會變為 0,這樣我們就將最低位的那個 1 移除了。

因此,如果 \(n\) 是正整數並且 \(\texttt{n & (n - 1) = 0}\),那麼 \(n\) 就是 2 的冪。

第二個技巧是\(\texttt{n & (-n)}\) 其中 \(-n\)

\(n\) 的相反數,是一個負數。該位運算技巧可以直接獲取 \(n\) 二進位制表示的最低位的 1。

由於負數是按照補碼規則在計算機中儲存的,\(-n\) 的二進位制表示為 \(n\) 的二進位制表示的每一位取反再加上 1,因此它的原理如下:

假設 \(n\) 的二進位制表示為 \((a 10\cdots 0)_2\) ,其中 \(a\) 表示若干個高位,1 表示最低位的那個 1,\(0\cdots 0\) 表示後面的若干個 0,那麼 \(-n\) 的二進位制表示為:

\[(\bar{a} 01\cdots1)_2 + (1)_2 = (\bar{a} 10\cdots0)_2 \]

其中 \(\bar{a}\)

表示將 \(a\) 每一位取反。我們將 \((a 10\cdots 0)_2\)\((\bar{a} 10\cdots0)_2\) 進行按位與運算,高位全部變為 0,最低位的 1 以及之後的所有 0 不變,這樣我們就獲取了 \(n\) 二進位制表示的最低位的 1。

因此,如果 \(n\) 是正整數並且 \(\texttt{n & (-n) = n}\),那麼 \(n\) 就是 2 的冪。

注意點

在一些語言中,位運算的優先順序較低,需要注意運算順序。

class Solution {
public:
    bool isPowerOfTwo(int n) {
        return n > 0 && (n & (n - 1)) == 0;
    }
};
class Solution {
public:
    bool isPowerOfTwo(int n) {
        return n > 0 && (n & -n) == n;
    }
};