1. 程式人生 > >演算法學習筆記(五) 遞迴之 快速冪、斐波那契矩陣加速

演算法學習筆記(五) 遞迴之 快速冪、斐波那契矩陣加速

遞迴的定義

遞迴和迭代是程式設計中最為常用的基本技巧,而且遞迴常常比迭代更為簡潔和強大。它的定義就是:直接或間接呼叫自身。經典問題有:冪運算、階乘、組合數、斐波那契數列、漢諾塔等。其演算法思想:

  • 原問題可分解子問題(必要條件);
  • 原與分解後的子問題相似(遞迴方程);
  • 分解次數有限(子問題有窮);
  • 最終問題可直接解決(遞迴邊界);

對於遞迴的應用與優化,直接遞迴時要預估時空複雜度,以免出現用時過長或者棧溢位。優化遞迴就是以不做重複的事兒為原則進行。對於常見數列問題,常常會有遞推公式,也即 f(n) 和 f(n-1) 的關係式,由遞推公式其實就很容易寫出遞迴演算法的程式碼,這裡要重新詳細說一下遞迴和遞推的區別:

  • 遞迴:將問題規模為n的問題,降解成若干個規模為n-1的問題,依次降解,直到問題規模可求,求出低階規模的解,代入高階問題中,直至求出規模為n的問題的解, ( n  ->  0);
  • 遞推:構造低階的規模(如規模為i,一般 i=0 ) 的問題,並求出解,推匯出問題規模為i+1的問題以及解,依次推到規模為n的問題, (0  ->  n);

快速冪


直接轉換成程式碼,時間複雜度由樸素冪運算的 O(n) -> O(logn) :

/* a 的  n 次方的快速冪,C 程式碼 */
int quickpower(int a, int n) {
	if (n == 0)
		return 1;

	if (n % 2 == 1)
		return quickpower(a, n / 2) * quickpower(a, n / 2) * a;
	else
		return quickpower(a, n / 2) * quickpower(a, n / 2);
}

斐波那契數列


轉換為程式碼,時間複雜度由直接遞迴的 O(n^2) -> O(logn) , 下面的實驗用 Python 實現,如果用 C++ 過載乘法運算子,則可以很大程度複用快速冪程式碼了就:

from time import clock
from functools import reduce

# 遞迴計算斐波那契數列 , python3 實現
def fib1(n):
    if n <= 1 :
        return 1
    else :
        return fib1(n - 1) + fib1(n - 2)

# 計算 a, b (都是 2×2 的矩陣) 的乘積 
def mul(a, b):
    r = [[0, 0], [0, 0]]
    r[0][0] = a[0][0] * b[0][0] + a[0][1] * b[1][0];
    r[0][1] = a[0][0] * b[0][1] + a[0][1] * b[1][1];
    r[1][0] = a[1][0] * b[0][0] + a[1][1] * b[1][0];
    r[1][1] = a[1][0] * b[0][1] + a[1][1] * b[1][1];
    return r;

# 遞迴加速計算斐波那契數列 O(n^2) -> O(logn)
def fib(n):
    if n == 0:
        return [[1, 0], [0, 1]]
    if n == 1:
        return [[1, 1], [1, 0]]
    if n % 2 == 0 :
        return mul(fib(int(n / 2)), fib(int(n / 2)))
    else:
        return reduce(mul,[fib(int(n / 2)),fib(int(n / 2)),[[1, 1], [1, 0]]])

if __name__ == '__main__':
    starttime = clock()
    print(fib1(35))  
    endtime = clock()
    print('直接計算用遞迴:', endtime - starttime)
    starttime = clock()
    print(fib(35)[0][0])
    endtime = clock()
    print('矩陣遞迴冪加速:', endtime - starttime)

''' 
試驗執行結果:
14930352
直接計算用遞迴: 5.524596036360783
14930352
矩陣遞迴冪加速: 0.00015129910309763517
'''

【原文地址:http://blog.csdn.net/thisinnocence】