別人家的面試題:一個整數是否是“4”的N次冪

十年蹤跡發表於2016-05-30

這是 leetcode.com 的第二篇。與上一篇一樣,我們討論一道相對簡單的問題,因為學習總講究循序漸進。而且,就算是簡單的問題,追求演算法的極致的話,其中也是有大學問的。

“4”的整數次冪

給定一個32位有符號整數(32 bit signed integer),寫一個函式,檢查這個整數是否是“4”的N次冪,這裡的N是非負整數。

例如:

  • 給定 num = 16,返回 true,因為 16 = 42
  • 給定 num = 5,返回 flase

附加條件: 你能夠不用迴圈和遞迴嗎?

解題思路

如果忽略“附加條件”,這題還挺簡單的對吧?簡直是信手拈來:

版本1

版本1 好像很簡單、很強大的樣子,它的時間複雜度是 log4N。有同學說,還可以做一些微小的改動:

版本1.1

上面的程式碼用位移替代除法,在其他語言中更快,鑑於 JS 通常情況下非常坑的位運算操作,不一定速度能變快。

好了,最關鍵的是,不管是 版本1 還是 版本1.1 似乎都不滿足我們前面提到的“附加條件”,即不使用迴圈和遞迴,或者說,我們需要尋找 O(1) 的解法。

按照慣例,大家先思考10秒鐘,然後往下看 ——


不用迴圈和遞迴

其實這道題真心有好多種思路,計算指數之類的對數學系學霸們完全不是問題嘛:

版本2

嗯,通過對數公式 logm(n) = log(n) / log(m) 求出指數,然後判斷指數是不是一個整數,這樣就可以不用迴圈和遞迴解決問題。而且,還要注意細節,可以將 log4 當做常量抽取出來,這樣不用每次都重複計算,果然是學霸範兒。

不過呢,利用 Math.log 方法也算是某種意義上的犯規吧,有沒有不用數學函式,用原生方法來解決呢?

當然有了!而且還不止一種,大家可以繼續想30秒,要至少想出一種哦 ——


不用內建函式

這個問題的關鍵思路和上一道題類似,先考慮“4”的冪的二進位制表示:

  • 40 = 1B
  • 41 = 100B
  • 42 = 10000B
  • 43 = 1000000B
  • ……

也就是每個數比上一個數的二進位制後面多兩個零嘛。最重要的是,“4”的冪的二進位制數只有 1 個“1”。如果仔細閱讀過上一篇,你就會知道,判斷一個二進位制數只有 1 個“1”,只需要:

但是,二進位制數只有 1 個“1”只是“4”的冪的必要非充分條件,因為“2”的奇數次冪也只有 1 個“1”。所以,我們還需要附加的判斷:

為什麼是 num & 0xAAAAAAAA === 0? 因為這個確保 num 的二進位制的那個 “1” 出現在“奇數位”上,也就確保了這個數確實是“4”的冪,而不僅僅只是“2”的冪。

最後,我們得到完整的版本:

版本3

上面的程式碼需要加上 num > 0,是因為 0 要排除在外,否則 (0 & -1) === 0 也是 true


其他版本

上面的版本已經符合了我們的需求,時間複雜度是 O(1),不用迴圈和遞迴。

此外,我們還可以有其他的版本,它們嚴格來說有的還是“犯規”,但是我們還是可以學習一下這些思路:

版本4:用 Math.sqrt

版本5:用正規表示式

以上就是所有的內容,這道題有非常多種思路,相當有趣,也比較考驗基本功。如果你有自己的思路,可以留言參與討論。

下一期我們討論另外一道題,這道題比這兩道題要難一些,但也更有趣:給定一個正整數 n,將它拆成至少兩個正整數之和,對拆出的正整數求乘積,返回能夠得到的乘積最大的結果

想一想你的解法是什麼?你能夠儘可能減少演算法的時間複雜度嗎?期待你的答案~~

打賞支援我寫出更多好文章,謝謝!

打賞作者

打賞支援我寫出更多好文章,謝謝!

任選一種支付方式

別人家的面試題:一個整數是否是“4”的N次冪 別人家的面試題:一個整數是否是“4”的N次冪

相關文章