可能存在無限遞迴 遞迴

2021-10-14 17:21:23 字數 1732 閱讀 3130

一、什麼樣的問題可以用遞迴來解決?

遞迴問題需要滿足的三個條件:

1、問題的解可以分解為幾個子問題《資料規模更小的問題》的解

2、問題與子問題,除了資料規模不同,求解思路完全一樣

3、存在遞迴終止條件《不會無限巢狀》

二、為什麼使用遞迴?遞迴的優缺點?

1.優點:**的表達力很強,寫起來簡潔。

2.缺點:

時間效率上,每次遞迴呼叫都會帶來時間成本;還有可能造成重複計算的風險;

空間複雜度上,每次遞迴呼叫都會在記憶體棧中儲存一次現場資料,所以遞迴**空間複雜度空間複雜度高;而且伴隨著空間複雜度;遞迴**還有堆疊溢位風險

三、如何編寫遞迴**?

1、寫遞迴公式,找終止條件 **

舉例:走台階問題:即假設有 n 個台階,每次只能跨 1 個台階或 2 個台階,問走這 n 個台階有多少種走法?

解釋:step1、寫遞推公式;因為每次只能走1個或者2個台階,所以最後一步可以是走1個台階,也可以是走2個台階;問題的結果就變成n-1級台階的n-2級台階的走法之和

f(n) = f(n-1) + f(n-2)   // 遞推公式
step2、看終止條件;遞迴公式顯示:當n<2時,就不成立了。所以終止條件就是n=1;n=2兩種case

f(1) = 1;

f(2) = 2;

f(n) = f(n-1)+f(n-2)

step3、寫遞迴**;

int f(int n)
2、遞迴**要警惕堆疊溢位

原因:函式呼叫會使用棧來儲存臨時變數《在函式返回時,執行出棧》;而遞迴函式會重複呼叫函式自身《直到終止條件出才開始執行出棧》;所以容易造成堆疊溢位。

避免:在**中宣告乙個全域性變數《最大遞迴呼叫深度》;遞迴呼叫超過該深度後就直接返回報錯;

// 全域性變數,表示遞迴的深度。

int depth = 0;

int f(int n)

3、遞迴**要警惕重複計算

如走台階例子所示:部分節點被重複計算了多次;帶來效能損耗。如圖中 f(4), f(3), f(2), f(1)

解決:可以通過乙個資料結構《比如雜湊表》 來儲存已經求解過的f(k);用查詢替換計算。

public int f(int n) 

int ret = f(n-1) + f(n-2);

hassolvedlist.put(n, ret);

return ret;

}

4、遞迴**改非遞迴**《所有的都可以改》

// 跳台階的例子

int f(int n)

return ret;

}

三、課後思考:

問:平時除錯**一般喜歡使用 ide 的單步跟蹤功能,但對於規模比較大、遞迴層次很深的遞迴**,幾乎無法使用這種除錯方式。對於遞迴**,有什麼好的除錯方法呢?

答:1、列印日誌,查遞迴值;

2,拿到遞迴值,輸入條件斷點;

3、結合條件斷點進行除錯。

可能存在無限遞迴 第3章 遞迴

遞迴只是讓解決方案更清晰,並沒有效能上的優勢。實際上,在有些情況下,使用迴圈的效能更好。如果使用迴圈,程式的效能可能更高 如果使用遞迴,程式可能更容易理解。遞迴函式的組成 1.基線條件 base case 即函式不再呼叫自己,從而避免無限迴圈 2.遞迴條件 recursive case 即自己呼叫自...

可能存在無限遞迴 Python之遞迴函式

我們在前面的章節中,很多次的看到了在函式中呼叫別的函式的情況,如果乙個函式在內部呼叫了自身,這個函式就被稱為遞迴函式。高斯求和 def sum number n total 0 for i in range 1,n 1 total i return total sum sum number 100 ...

無限分類 遞迴

在所有欄目 地區等 下拉列表中,這個類非常好用。具有這個結構的陣列,不是這樣的話,可以改類的實現 list array 1 array id 1 pid 0,name 一級欄目一 2 array id 2 pid 0,name 一級欄目二 3 array id 3 pid 1,name 二級欄目一 ...