遞迴之再探

2021-12-30 04:25:51 字數 1741 閱讀 2568

遞迴是好理解還是不好理解?

很多人說,遞迴很簡單,但是面對很多遞迴的題目,我卻覺得十分困難。

遞迴是一種工具

我們有幾個步驟去做

1.首先,找出關鍵的步驟,這是演算法的核心,每一步都要迴圈的列子,即大問題分成小問題適用的演算法。

2.然後找出停止規則,遞迴不能無限向前,必須停止,然後往回走。

3.列出演算法大綱,即**框架。

4.檢查終止。

5.畫出遞迴樹,觀察是否正確。

有人說遞迴就是有去(遞去)有回(歸來)。

具體來說,為什麼可以有去

這要求遞迴的問題需要是可以用同樣的解題思路來回答除了規模小不同其他完全一樣的問題。

為什麼可以有回

這要求這些問題不斷從大到小,從近及遠的過程中,會有乙個終點,乙個臨界點,乙個baseline,乙個你到了那個點就不用再往更小,更遠的地方走下去的點,然後從那個點開始,原路返回到原點。

當思考遞迴題目時,很多人去探尋遞迴的每一步,思考全過程是怎麼解決問題的,所以一直往前,到底後,往後,來來往往,思考不出各結果。

但觀察遞迴的基本思想——把規模大的問題轉化為規模小的相似的子問題來解決。在函式實現時,因為解決大問題的方法和解決小問題的方法往往是同乙個方法,所以就產生了函式呼叫它自身的情況。另外這個解決問題的函式必須有明顯的結束條件,這樣就不會產生無限遞迴的情況了。

所以我們考慮的僅僅是乙個大的問題,然後把這個問題去拆分為相同的小問題即可,這才是遞迴的思想。

如果將其用程式表達出來,則可表示為

很多時候,我們可以用上簡單的遞迴,比如很明顯的函式關係,反轉,遍歷等。但是,有些遞迴卻讓我摸不著頭腦,比如,全排列,子集。

這時候我們需要遞迴樹的幫忙

以上圖為列,箭頭表示遞迴的走向,圖為3層漢諾塔的示意圖,當move第乙個引數為0時,停止,所以,遞迴中,總共進行了7次的實際操作,這也是漢諾塔步數的公式,2的n次方-1,即完全二叉樹的分支節點數。在此從簡短的過程中,我們可以思考遞迴的走向。

尾遞迴如果函式最後執行的語句是對函式自身的遞迴呼叫,則可以呼叫引數賦給遞迴呼叫中指定的值並重複整個函式而消除此呼叫。

如圖,右邊p可以直接返回第一步。

所以,尾遞迴和迭代相似,一般不單獨使用。

回溯當發生與問題需求不一致的情況時,演算法移構造的解部分並進行倒退,以嘗試另外一種可能。

1.針對所給問題,確定問題的解空間:

首先應明確定義問題的解空間,問題的解空間應至少包含問題的乙個(最優)解。

2確定結點的擴充套件搜尋規則

3以深度優先方式搜尋解空間,並在搜尋過程中用剪枝函式避免無效搜尋。

所以回溯可以差異地理解為暴力搜尋?(個人認為)當乙個方向錯誤後,回到上乙個遞迴中。**結構如下:

int a[n];

try(int i) }}

}由**可以看出,for列舉所有可能性,滿足條件將進行下一步遞迴操作,當被約束時的列舉沒有滿足if的條件時,最底層遞迴終止,進行回溯,之前應該做必要的清理工作,如此直到滿足終止條件為止。

遞迴之再探

有人說 遞迴就是有去 遞去 有回 歸來 所以遞迴過程可以分解為兩部分,一部分為分解,一部分為求解。具體來說,為什麼可以有去?這要求遞迴的問題需要是可以用同樣的解題思路來回答除了規模大 小不同其他完全一樣的問題。為什麼可以有回?這要求這些問題不斷從大到小,從近及遠的過程中,會有乙個終點,乙個臨界點,乙...

STL之再探迭代器

迭代器被繫結到乙個容器上,可用來向容器插入元素。back inserter建立乙個使用push back的迭代器 front inserter建立乙個使用push front的迭代器 inserter建立乙個使用insert的迭代器,此函式接受哦第二個引數,這個引數必須是指向乙個給定容器的迭代器。元...

再探函式引數

c函式的所有引數均以 傳值呼叫 方式進行傳遞。這意味著函式將獲得引數值的乙份拷貝,這樣函式可以放心修改這個拷貝值,而不必擔心會修改呼叫程式實際傳遞給它的引數。普通資料型別主要包括 如下面 所示 include void swap int x int y int main 我們原本是希望編寫乙個函式,...