用遞推關係顯性公式替代遞迴的程式設計方法

2021-06-23 06:33:54 字數 1660 閱讀 3499

一般來說,遞迴有兩種。

一種是行為的遞迴,比如樹的遍歷;另一種是計算的遞迴,比如斐波那契數列和複利計算。

我們今天嘗試對計算的遞迴進行優化。

我們從斐波那契數列作為例子

一般的**如下:

//函式

int fun(int n)

//主體

int main()

分析:上面這種解決方法有乙個致命缺陷,遞迴函式的呼叫非常消耗堆疊資源。

我們先來看一下上面程式執行時的堆疊呼叫情況:

大家可以發現,在峰值時程式開闢了10個fun函式的呼叫堆疊。

按照這種情況,當n足夠大時,那對記憶體的消耗會非常巨大。

使用遞迴的程式設計方法(特別是一些計算數值問題,比如斐波那契數列、複利)都存在這樣的通病。

原因在於擺在我們面前的遞推關係是乙個第n項與前幾項之間的關係。

解決方法:

如果我們能將這種第n項和前幾項相關的關係轉換成只和n相關的公式,那麼就解決遞迴帶來的堆疊消耗。

這種轉換的方法就是今天要介紹的常係數k階線性齊次遞推關係的顯性公式求解。

常係數k階線性齊次遞推關係是什麼?

它是一種第n項與前幾項之間的關係,形如:a[n]=c[1]*a[n-1]+c[2]*a[n-2]+…+c[k]*a[n-k]。

我們所熟知的斐波那契數列、複利等計算公式都屬於常係數k階線性齊次遞推關係。

求解常係數k階線性齊次遞推關係的顯性公式的步驟

求解的第一步:構建特徵方程

假設遞推關係如下:

則我們構建的特徵方程如下:

將特徵方程進行簡化(等式兩邊都除以r^(n-k)):

求解的第二步:求解特徵根

特徵根就是特徵方程的解。

我們這裡不介紹如何求解特徵方程,這牽涉到別的數學知識。

只是假設最終會解出t個不相等的根r[1]-r[t],其重複數量分別為m[1],m[2],…,m[t]。

求解的第四步:算出a1.0、a1.1、…、at.m的值

所有的遞推關係都會需要初始項。

我們在這一步要做的事利用將初始項代入線性方程的模板,組成線性方程組,計算出a1.0、a1.1、…、at.m的值。

這樣就最終確定了顯性方程。

以斐波那契數列為例進行實戰

使用顯性公式的**

//函式

int fun(int n)

//主體

int main()

遞推公式 黑科技

有乙個遞推式的模板,你給的值越多 main中的x值越多 遞推式得出的結果越準確 據說是杜教的模板。可不是很會用,找了幾個遞推的題,嘗試了一下,發現對於最後取模固定的題,還是蠻好用。如果每次取模都不一樣,我找的題,都用不好。好多地方看不懂 也不知道真 求不了,還是我不會用 tat 哪位dalao 可以...

約瑟夫環 遞推公式

遞推公式 f n,m f n 1,m m n f n,m f n 1,m m nf n 1,m 1 2 3 4 5 6 7 8 9 1001 2345 6789 1234 5678 91045 6789 10127 89101 24510 1245 7845 78101 81014 5458 101...

拯救LongMM (遞推公式求解)

拯救l o n g m m l a n p a s c c p p 題目描述 longdd 將軍為了平息延續數年戰亂,決定釋放戰俘營中所有的俘虜。然而,longdd 將軍不打算釋放敵軍的統帥longmm 因為這個傢伙異常聰明,是個難纏的 對手。所以longdd 將軍決定把longmm 用鍊子固定到牆...