Promise yourself to be so strong that nothing can disturb your peace of mind.
答應自己要堅強,不讓任何事物煩擾內心的平靜。
給一個函數f(x),返回一個不小於x的最小的2的n次方。描述的比較繞口,舉個例子。
f(7)=8
f(9)=16
f(30)=32
f(64)=64
注意:
x是正整數
0<x<Integer.MAX_VALUE
我們看到返回的結果都是2的n次方,並且是不小於x的最小的2的n次方。如果把2的n次方轉換成二進位我們就會發現,只有一個位上是1,其他位上全部是0,隨便舉幾個數字看一下
所以最簡單的一種方式就是通過循環來計算,先用x和1比較,如果大於1,那麼1就往左移一位,繼續比較……,一直這樣下去,直到不小於為止,原理比較簡單,來看下代碼
1public int lowPower(int x) {
2 int n = 1;
3 while (x > n)
4 n <<= 1;
5 return n;
6}
代碼非常簡潔,基本沒什麼難度
再來看下位運算,我們隨便舉個例子,比如53,他的二進位位如下,如果要找到不小於53的最小的2的n次方,我們只需要把53的二進位位中最左邊的1往左移一位,其他的全部變為0即可。
所以一種最簡單的方式就是通過移位運算,把53最左邊的1全部往右邊鋪開,就變成了00111111,然後再加1就變成了了01000000。最後來看下代碼
1public int lowPower(int x) {
2 //這裡把最左邊的1全部往右邊鋪開
3 x |= x >>> 1;
4 x |= x >>> 2;
5 x |= x >>> 4;
6 x |= x >>> 8;
7 x |= x >>> 16;
8 //最後再加1返回
9 return x + 1;
10}
但是這裡有個小問題就是,如果x本來就是2的n次方,比如x是16,運算的結果就會變成32,與我們實際要求不符。所以這裡我們可以先讓x-1,然後再進行運算,所以正確答案應該是下面這樣
1public int lowPower(int x) {
2 //這裡把最左邊的1全部往右邊鋪開
3 //x--;
4 x -= 1;
5 x |= x >>> 1;
6 x |= x >>> 2;
7 x |= x >>> 4;
8 x |= x >>> 8;
9 x |= x >>> 16;
10 //最後再加1返回
11 return x + 1;
12}
或者也可以改成這樣,當然沒有上面的代碼簡潔
1public int lowPower(int x) {
2 if (x == 1)
3 return 1;
4 //這裡把最左邊的1全部往右邊鋪開
5 x -= 1;
6 x |= x >>> 1;
7 x |= x >>> 2;
8 x |= x >>> 4;
9 x |= x >>> 8;
10 x |= x >>> 16;
11 //執行完下面這行代碼,x相當於把
12 //後面的1全部減掉了,只留下最前
13 //面的那個1,也是2的n次方,
14 //只不過這個是小於原來x的最大的
15 //2的n次方
16 x -= x >> 1;
17 //然後我們再把它往左移一位,就變
18 //成了不小於原來x的最小的2的n次方
19 return x << 1;
20}
如果大家經常看源碼可能對這個算法比較了解,這是HashMap中專門計算數組長度的,我們知道HashMap是數組加鍊表的結構,數組的大小就是2的n次方,無論你傳入的大小是多少,他都會通過上面的計算。
長按上圖,識別圖中二維碼之後即可關注。
如果覺得有用就點個"贊"吧