數據結構與算法經典問題解析-Java語言描述(第二章遞歸和回溯)

2020年2月23日
1.什麼是遞歸?
任何調用自身的函數稱爲遞歸。用遞歸方法求解問題,要點在於遞歸函數調用自身 去解決一個規模比原始問題小一些的問題。這個過程稱爲遞歸步驟。遞歸步驟會導致更 多的遞歸調用。因此,保證遞歸過程能夠終止是很重要的。每次函數都會用比原問題規 模更小的問題來調用自身。問題隨着規模不斷變小必須能最終收斂到基本情形。

2.爲什麼要用遞歸
遞歸是從數學領域借鑑過來的一種有用的技術。遞歸代碼通常比迭代代碼更加簡潔 易慷。一般來說,在編譯或解釋時,循環會轉化爲遞歸函數。當任務能夠被相似的子任 務定義時,採用遞歸處理十分有效。例如,排序、搜索和遍歷等問題往往有簡潔的遞歸 解決方案。

3.遞歸函數的格式
遞歸函數在執行一個任務時,需要調用函數自身來完成一些子任務。在某些時候, 函數不需要繼續調用函數自身就可以完成當前子任務。函數不再遞歸的情況稱作基本情 形(base case,也稱爲基本情況)。而函數調用自身來執行子任務的情況就稱作遞歸情形。可以用如下的形式描述所有的遞歸函數。
在這裏插入圖片描述

4.遞歸與迭代
•當到達基本情形時,遞歸終止。
*每次遞歸調用都需要額外的空間用於棧幀(內存)開銷。
•如果出現無窮遞歸,程序可能會耗盡內存,並出現棧溢出。
*某些問題採用遞歸方法更容易解決。
迭代
•當循環條件爲假時,迭代終止。
*每次迭代不需要任何額外的空間開銷。
•由於沒有額外的空間開銷,所以若出現死循環,則程序會一直循環執行。採用迭代求解問題可能沒有遞歸解決方案那樣顯而易見。

通常,迭代解決方案比遞歸解決方案更加有效(因爲後者有函數調用的開銷)。一個迭代算法可以通過使用棧代替遞歸函數的方式來實現,但通常是得不償失的,這意味着任何能用遞歸求解的問題也能用迭代來求解。對於某些問題,沒有明顯的迭代求解算法。

5.什麼是回溯
回溯是一種採用分治策略進行窮舉搜索的方法。
有時求解一個問題的最好算法是嘗試所有的可能性。
這種方法通常很慢,但有標準工具能夠輔助該過程。
工具:生成基本對象的算法,排列、組合、一般字符串 等等。
通過剪枝回溯可以加速的窮舉搜索。

6.回溯算法的經典用例
二進制串:產生所有的二進制串。
生成k進制串。
揹包問題。
廣義字符串。
哈密頓迴路。
圖着色問題。

7.回溯與遞歸的區別。
遞歸:
爲了描述問題的某一狀態,必須用到該狀態的上一狀態,而描述上一狀態,又必須用到上一狀態的上一狀態……這種用自已來定義自己的方法,稱爲遞歸定義。形式如 f(n) = n*f(n-1), if n=0,f(n)=1。遞歸是一種算法結構,遞歸會出現在子程序中自己調用自己或間接地自己調用自己。最直接的遞歸應用就是計算連續數的階乘,計算規律:n!=(n-1)!*n。
回溯:
從問題的某一種可能出發, 搜索從這種情況出發所能達到的所有可能, 當這一條路走到” 盡頭 “的時候, 再倒回出發點, 從另一個可能出發, 繼續搜索. 這種不斷” 回溯 “尋找解的方法, 稱作” 回溯法 “。回溯是一種算法思想,可以用遞歸實現。通俗點講回溯就是一種試探,類似於窮舉,但回溯有“剪枝”功能。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章