快速求冪:快速冪算法


快速冪,就是快速算底數的n次冪。其時間復雜度為 O(logN), 與朴素的O(N)相比效率有了極大的提高。

朴素算法

在要求算出一個數字的n次冪時,最容易想到的便是朴素的循環累乘:

int normalPower(int base, int exponent) {
    while (exponent > 0) {
        base *= base;
        --exponent;
    }
    return base;
}

很明顯,這種方法的時間復雜度為O(N);

快速冪算法

根據二進制的性質以及編程語言中方便的與運算符&和移位運算符>>,有人提出了快速冪的算法,其時間復雜度為O(logN)。對這兩個操作符不明白的同學可以先看文末的簡述。
1.快速冪思想
例如計算ab這樣一個數,我們指數b以轉換二進制的形式進行分解,將其寫成二進制中每一位乘上該位的權重(從右往左,第i位的權為2i-1)。
例如:a13 = a2^0+2^2+2^3 = a2^0a2^2a2^3
2.快速冪實現
在這里我們先給出快速冪實現的代碼,方便后續進行對照講解

int fastPower(int base, int exponent) {
    int sum = 1;
    while (exponent != 0) {
        if ((exponent & 1) != 0) {
            sum *= base;
        }
        exponent = expnonent >> 1;  // 對指數進行移位
        base *= base;               // 讓base的次冪以2的倍數增長
    }
    return sum;
}

需要額外注意的是,&操作符的運算符低於>之類的比較運算符,也低於==!=運算符。
3.快速冪講解
首先可以看到,循環的終止條件為指數e為0,且每次循環e都會右移一位,而自然數N的二進制長度為log2N,因此這個循環至多遍歷log2N次。即它的時間復雜度為O(logN)
我們在每次指數右移的同時,讓底數base=base*base。這樣一來,第一次循環結束后base的大小變為原來的2=21次方倍,第二次后變為原來的21*21=22次方倍...最終,我們在第n次循環中sum所乘的base總是base2^(n-1)。保證了算法的正確性。而每次base2^(n-1),總能在下一次的循環中利用到base2^n的計算中,減少了程序的時間消耗與空間消耗。
假設我們輸入了fastPower(bbasese, 13)這樣一個函數,那么按照上面的定義,13應該是被理解為二進制串1101,在每次開始都進行和1相與,為1時才進行sum和bbasese的相乘,聯系上一段話,我們不難推斷出我們能夠按照base13 = base2^0+2^2+2^3 = base2^0base2^2base2^3的順序計算。


快速冪預備知識
1.二進制
相信大家都知道二進制的原理,這里我們主要用到十進制與二進制相互轉換的原理。
舉個例子,6的二進制是110,那么6便可以標示成22+21
2.與運算符&
這是一個二元運算符,返回左右兩數以二進制形式相與后的結果。例如x & 1 == 1則表示x為奇數,x & 1 == 0則為偶數。
3.移位運算符>>
顧名思義,這是令一個數的二進制形式移位的操作符。該操作符指向右邊,因此是右移,例如1011>>1 = 101。相似的,還有左移用的操作符<<,不過這里用不上。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM