題目描述:給定一個整數 n,判斷它是否為 2 的冪次方。2 的冪次方包括 1(2⁰)、2(2¹)、4(2²)、8(2³)等。
解題思路:利用位元運算的關鍵性質:2 的冪次方在二進位表示中有且僅有一個位元為 1。例如,4 的二進位是 100,8 的二進位是 1000。利用這個性質,若 n 為 2 的冪次方,則 n & (n-1) 的結果必為 0,因為 n-1 的所有位元恰好與 n 互補(例如 100 & 011 = 000)。因此只需檢查兩個條件:n 必須大於 0(排除 0 和負數),以及 n & (n-1) == 0。
時間複雜度:O(1) — 僅進行一次位元運算,與輸入大小無關,為常數時間。
空間複雜度:O(1) — 不需要額外的儲存空間,只使用固定數量的變數。
1. If n <= 0, return false (powers of two are strictly positive) 2. Compute n & (n - 1): - If n is a power of two, its binary has exactly one '1' bit - n - 1 flips all bits from the lowest '1' downward - ANDing them together clears the single set bit, giving 0 3. Return true if (n & (n - 1)) == 0, false otherwise
方法一:遞迴法 時間複雜度:O(log n) — 每次遞迴將 n 除以 2。不斷判斷 n 是否能被 2 整除,若不能則返回 false,若 n 等於 1 則返回 true。空間複雜度 O(log n)(遞迴堆疊)。
方法二:迭代除法 時間複雜度:O(log n) — 使用迴圈不斷將 n 除以 2,直到 n 變為 1 或出現奇數為止。優點是不需要額外堆疊空間,但相比位元運算仍較慢。
方法三:預計算整數範圍內所有 2 的冪次方
時間複雜度:O(1) — 由於 int 範圍內 2 的冪次方只有 31 個(2⁰ 到 2³⁰),可以預先儲存在 set 中或直接與最大 2 的冪次方做取模運算:n > 0 && (1073741824 % n == 0)。
__builtin_popcount(n) 等編譯器內建函式來判斷,並比較其與手動位元運算的效能差異?