如果m和n是正整數,那麼m^n就是把m連乘n次,這是乙個很沒效率的方法。其實用分置+遞迴可以更有效地解決該問題!
首先來看看我最初寫的程式吧~
int r_power(int m,int n)
其中用到的其實是非常樸素的遞迴方式,無法是將m^n均分成兩部分,但是可能會存在奇偶等問題的干擾,所以乾脆將兩個遞迴函式的係數分別設為n/2和n-n/2。而遞迴結束的條件是n==1或n==2。這樣其實只要做o(lgn)次乘法就能解決問題了。
不過其實這段**還是存在缺陷的,它對遞迴邊界條件的判斷而且將原函式分治為n/2和n-n/2雖然**是少寫了幾行,但是n/2和n-n/2至多差1,最後一行完全可用
return r_power(m,n/2)*r_power(m,n/2)*m;//若n為奇數
來代替,用乙個變數儲存r_power(m,n/2)就得到了下面的執行效率更好的**return r_power(m,n/2)*r_power(m,n/2);//若n為偶數數
int r_power(int m,int n)
而這時的條件發生了一定的變化即要判斷當前n的奇偶情況,其中語句
if(n&0x01ul==0)
通過判斷n的二進位制的最低位來判斷奇偶性~再根據奇偶性分別進行不同的操作
但是考慮到呼叫遞迴函式耗費較大,其實用非遞迴的方式完全可以解決該問題~先看**
int r_power(int m,int n)
return ans;
}
首先假設m=2,n=5,則n用二進位制可表示為101,則m^n為m^(101)=m^(2^0*1)*m^(2^1*0)*m^(2^2*1),所以完全可以講n次乘方化為對n的每個二進位制位所表示的數的乘方相乘,其實m^(2^a)=(m^(2^(a-1)))^2,說明n的二進位制位關於m的乘方完全可以由n的二進位制位的前一位關於m的乘方的自乘所得。因此就有了**中的m,開始它表示m^(2^0),隨後隨著n的不斷右移,即不斷將n的高位移到第一位,m自乘獲得與n的該位匹配的乘數,通過
if(n&0x01ul)
來判斷當前n的最低位是否為0,從而決定是否將當前的m與ans相乘。由此,當n的有效位(即是1的位)不存在的時候,自乘也就結束了。
總的來說,這題還是比較簡單的,但是其中用到的思想非常值得學習
每日一小練 數值自乘遞迴解
上得廳堂,下得廚房,寫得 翻得圍牆,歡迎來到睿不可擋的每日一小練!題目 數值自乘遞迴解 內容 假設乙個n與m是正整數,那麼m n就是把m連乘n次,這是乙個非常沒有效率的方法。試試編寫乙個更有效率的程式,應該以少量n 1個乘法作為設計標準。我的解法 上來沒多想,開啟vs2013就敲了起來,問題果然非常...
遞迴與非遞迴習題
1.遞迴和非遞迴分別實現求第n個斐波那契數。includeint fib int n else 可以跳n節台階 是2 fib n 1 int main includeint fib int n if n 1 n 2 return 1 while a return f3 int main 2.編寫乙個...
遞迴與非遞迴演算法
一 題目分析 將非負十進位制整n轉換成b進製 其中b 2 16 將任意正整數n用2的冪次方表示 二 演算法設計 1 轉換進製問題 exer.cpp 遞迴演算法 遞迴出口 n b b 遞迴表示式 f n,b f n b,b n b b 遞迴棧表示 2 用二的冪次方表示任意正整數n問題 exer2.cp...