問題:
如何判斷一個給定的整數是否爲2的非負整數次冪?
通常的解法或者需要O(LOGN)的時間開銷;或者通過時間換空間策略,建立一個LOG(MAX)大小的hash table解決限定範圍內數據的判斷問題。我們需要意識到的是,後者事實上是把運行時的運算開銷前置到了編譯期,總的計算成本是一樣的。
前幾天在學習極客時間上吳詠煒老師的《現代C++實戰30講》課程(順便推薦吳詠煒老師的這門C++課程,需要有C++開發經驗)時,發現吳老師在範例代碼中展示了一種非常巧妙的算法:
X & (X - 1) == 0
思考了一下,發現這個算法非常優美且高效。其幾乎接近原子操作,和其他算法O(LogN)的時間開銷比起來判若雲泥。以至於我甚至一度懷疑這兩個命題的等價性。遂嘗試如下證明:
證明 ”X是2的非負整數次冪“ 與 ”X & (X - 1) == 0“ 是等價的;
充分性證明:
已知X是2的正整數次冪;可一般性假設X的二進制可表達爲m位上1,從m-1位到1位共m-1個0;任取Y < X, 可知Y的二進制表達中,第m位必爲0;顯見X & Y == 0; 可推知X & (X - 1) == 0;
必要性證明:
使用反證法。已知X&(X-1) == 0; 假設X不是2的正整數次冪;
則X的二進制表達爲m位上是1,從位到1位至少還還存在一個1;一般性假設第位是1;則有:
易得:
由於,可得:
進一步可得:
可推出:
即:
X - 1二進制表達中第m位必定爲1;可推出X & (X - 1) != 0;與已知矛盾,假設條件不成立;
等價性成立。證明完畢。
思考:
-
類似的高效等價操作還有:右移操作和➗2;
-
針對2的整數次冪存在這樣高效的算法,可以看做是使用二進制計數的紅利。其實對於任意X進制系統中,X的任意整數次冪的判斷是同樣高效的。