劍指offer 16——數值的整數次方

這道題可以利用二進制,就可以快速解決了。

原題

實現函數double Power(double base, int exponent),求base的exponent次方。不得使用庫函數,同時不需要考慮大數問題。

示例 1:

輸入: 2.00000, 10
輸出: 1024.00000

示例 2:

輸入: 2.10000, 3
輸出: 9.26100

示例 3:

輸入: 2.00000, -2
輸出: 0.25000
解釋: 2-2 = 1/2^2 = 1/4 = 0.25

說明:

  • -100.0 < x < 100.0

  • n 是 32 位有符號整數,其數值範圍是 [−2^31, 2^31 − 1] 。

原題url:https://leetcode-cn.com/problems/shu-zhi-de-zheng-shu-ci-fang-lcof/

解題

這道題,如果你是用正常計算的話,提交之後會發現報超時,因此,肯定需要尋找捷徑的。

因爲不能使用庫函數,而且上面普通方法也是會超時的,那麼問題的關鍵就是在如何快速計算。

而如果想快的,最好的辦法就是可以利用曾經計算的結果,避免重複計算。

我一開始的想法是,比如計算 2^6 ,從數學上來說,等同於計算 4^3。但如果要用這種邏輯的話,就必須要求傳入參數 n 是 2^w(其中 w 是正整數),否則計算邏輯會比較複雜。因此放棄該方案。

二進制

重點依舊是放在利用曾經計算的結果,避免重複計算上,那麼理想情況也就是計算 x^n 後,之後希望直接計算 x^2n,而x^2n = x^n * x^n = x^(n + n)

從上面的討論可以看出,計算冪,可以轉換成將指數進行合理的加法拆分。所謂合理,就是後一個是前一個的 2 倍,這樣的話,就自然聯想到要對指數從十進制轉爲二進制

7 = (111) = 1 * 2^2 + 1 * 2^1 + 1 * 2^0
9 = (1001) = 1 * 2^3 + 0 * 2^2 + 0 * 2^1 + 1 * 2^0

當然,上面是從大到小累加,實際計算時肯定是從小到大進行累加的。

說到二進制,肯定少不了位運算,那麼計算每一位二進制上的值,有什麼快速的方法呢?

有的,利用n & 1,求出最低位的值(0或者1),然後n >> 1,右移,相當於移除最低位,不停循環,也就能計算出二進制上每一位的值了。

接下來看看代碼:

class Solution {
    public double myPow(double x, int n) {
        if (x == 0) {
            return 0;
        }

        // 此處用long,是防止n是Integer.MIN_VALUE時,取反後直接就超過了Integer.MAX_VALUE
        long b = n;
        double res = 1.0;
        if(b < 0) {
            x = 1 / x;
            b = -b;
        }

        while(b > 0) {
            if ((b & 1) == 1) {
                res *= x;
            }
            // 底數擴大
            x *= x;
            // 指數右移
            b >>= 1;
        }
        return res;
    }
}

提交OK。

總結

以上就是這道題目我的解答過程了,不知道大家是否理解了。這道題利用二進制,就可以快速解決了。

有興趣的話可以訪問我的博客或者關注我的公衆號,說不定會有意外的驚喜。

https://death00.github.io/

公衆號:健程之道

點擊此處留言

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章