今天看到小夥在看一個判斷一個數是否爲2的N次方的博客,我有點印象,就過去裝逼了結果一下子還真沒想出來,裝逼失敗!
這道題目其實是leetcode上面的第231道題目,題目內容如下:
給定一個整數,編寫一個函數來判斷它是否是 2 的冪次方
我一開始是想到如果是10進制內10的多少次方的時候應該是什麼樣子:
10^n | 數值 | n |
---|---|---|
10^0 | 1 | 0 |
10^1 | 10 | 1 |
10^2 | 100 | 2 |
10^3 | 1000 | 3 |
我們很自然的看出來,如果我們平時的10進制,其實就是一位數上是1,其他都是0。這個想到我們計算2^n的時候,應該是1,2,4,8,16依次下去,由此想到這種情況下在二進制的情況:
2^n | 數值 | 10進制 |
---|---|---|
2^0 | 1 | 1 |
2^1 | 10 | 2 |
2^2 | 100 | 4 |
2^3 | 1000 | 8 |
我們其實很容易發現,2的多少次方的情況就是二進制位數上一個數是1其他都是0,我們的思路其實就是想辦法把二進制數中的1消掉,剩下的是0就行,當然前提條件是這個數>大於0,我們可以使用二進制的中的清零最低位的1操作x&(x-1),這個表示的是我們把最低位的1去掉,看看剩下的值,運算過程如下:
2^n | n | n-1 | n&n-1 |
---|---|---|---|
2^0 | 1 | 0 | 0 |
2^1 | 10 | 01 | 00 |
2^2 | 100 | 011 | 000 |
2^3 | 1000 | 0111 | 0000 |
其他情況也可以看看
十進制 | n | n-1 | n&n-1 |
---|---|---|---|
3 | 11 | 10 | 10 |
5 | 101 | 100 | 100 |
6 | 110 | 101 | 100 |
7 | 111 | 110 | 110 |
可以看到n&(n-1)的效果就是會把n的二進制位最低的那位1抹掉,在2^n次方的情況抹掉一個0剩下的就全是0了,其他情況的話不會是0,所以相應的只要位運算的操作就可以出來結果,代碼貼上,附上測試數據:
public class Leecode_231_35 {
public static void main(String[] args) {
Leecode_231_35 lc = new Leecode_231_35();
System.out.println(lc.isPowerOfTwo(0));
System.out.println(lc.isPowerOfTwo(1));
System.out.println(lc.isPowerOfTwo(2));
System.out.println(lc.isPowerOfTwo(3));
System.out.println(lc.isPowerOfTwo(4));
System.out.println(lc.isPowerOfTwo(5));
System.out.println(lc.isPowerOfTwo(6));
System.out.println(lc.isPowerOfTwo(7));
System.out.println(lc.isPowerOfTwo(8));
System.out.println(lc.isPowerOfTwo(9));
System.out.println(lc.isPowerOfTwo(-2147483648));
}
public boolean isPowerOfTwo(int n) {
return n > 0 && (n &= n - 1) == 0;
}
}
當然,這種高效一次運算的操作,自然時間複雜度就是最最讓人喜歡的O(1)了