怎麼更好地終極理解遞迴演算法

2021-08-14 14:17:24 字數 2979 閱讀 1479

遞迴真是個奇妙的思維方式。對一些簡單的遞迴問題,我總是驚嘆於遞迴描述問題和編寫**的簡潔。但是總感覺沒能融會貫通地理解遞迴,有時嘗試用大腦去深入「遞迴」,層次較深時便常產生進不去,出不來的感覺。這種狀態也導致我很難靈活地運用遞迴解決問題。有一天,我看到一句英文:「to iterate is human, to recurse, divine.」中文譯為:「人理解迭代,神理解遞迴。」然後,我心安理得地放棄了對遞迴的深入理解。直到看到王垠談程式語言最精華的原理時提到了遞迴,並說遞迴比迴圈表達能力強很多,而且效率幾乎一樣。再次喚醒了我對遞迴的理解探索。

我首先在知乎上發現了下面兩個例子,對比了遞迴和迴圈。

遞迴:你開啟面前這扇門,看到屋裡面還有一扇門(這門可能跟前面開啟的門一樣大小(靜),也可能門小了些(動)),你走過去,發現手中的鑰匙還可以開啟它,你推開門,發現裡面還有一扇門,你繼續開啟,。。。, 若干次之後,你開啟面前一扇門,發現只有一間屋子,沒有門了。 你開始原路返回,每走回一間屋子,你數一次,走到入口的時候,你可以回答出你到底用這鑰匙開了幾扇門。

迴圈:你開啟面前這扇門,看到屋裡面還有一扇門,(這門可能跟前面開啟的門一樣大小(靜),也可能門小了些(動)),你走過去,發現手中的鑰匙還可以開啟它,你推開門,發現裡面還有一扇門,(前面門如果一樣,這門也是一樣,第二扇門如果相比第一扇門變小了,這扇門也比第二扇門變小了(動靜如一,要麼沒有變化,要麼同樣的變化)),你繼續開啟這扇門,。。。,一直這樣走下去。 入口處的人始終等不到你回去告訴他答案。

該使用者這麼總結到:

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

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

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

為什麼可以」有回「?

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

上面的解釋幾乎回答了我已久的疑問:為什麼我老是有遞迴沒有真的在解決問題的感覺?

因為遞是描述問題,歸是解決問題。而我的大腦容易被遞佔據,只往遠方去了,連盡頭都沒走到,何談回的來。

《漫談遞迴:遞迴的思想》這篇文章將遞迴思想歸納為:

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

需注意的是,規模大轉化為規模小是核心思想,但遞迴並非是只做這步轉化,而是把規模大的問題分解為規模小的子問題和可以在子問題解決的基礎上剩餘的可以自行解決的部分。而後者就是歸的精髓所在,是在實際解決問題的過程。

我試圖把我理解到遞迴思想用遞迴用程式表達出來,確定了三個要素:遞 + 結束條件 + 歸。

functionrecursion(大規模)

else

}

但是,我很容易發現這樣描述遺漏了我經常會遇到的一種遞迴情況,比如遞迴遍歷的二叉樹的先序。我將這種情況用如下遞迴程式表達出來。

functionrecursion(大規模)

else

}

總結到這裡,我突然發現遞迴是為了最能表達這種思想,所以用「遞迴」這個詞,其實遞迴可以是「有去有回」,也可以是「有去無回」。但其根本是「由大往小地去,由近及遠地去」。「遞」是必需,「歸」並非必需,依賴於要解決的問題,有的需要去的路上解決,有的需要回來的路上解決。有遞無歸的遞迴其實就是我們很容易理解的一種分治思想。

其實理解遞迴可能沒有「歸」,只有去(分治)的情況後,我們應該想到遞迴也許可以既不需要在「去」的路上解決問題,也不需要在「歸」的路上解決問題,只需在路的盡頭解決問題,即在滿足停止條件時解決問題。遞迴的分治思想不一定是要把問題規模遞迴到最小,還可以是將問題遞迴窮舉其所有的情形,這時通常遞迴的表達力體現在將無法書寫的巢狀迴圈(不確定數量的巢狀迴圈)通過遞迴表達出來。

將這種遞迴情形用遞迴程式描述如下:

recursion()

else

}

}

由這個例子,可以發現這種遞迴對遞迴函式引數出現了設計要求,即便遞迴到盡頭,組合的字串規模(長度)也沒有變小,規模變小的是遞迴函式的乙個引數。可見,這種變化似乎一下將遞迴的靈活性大大地擴充套件了,所謂的大規模轉換為小規模需要有乙個更為廣義的理解了。

對遞迴的理解就暫時到這裡了,可以看出文章中提到關於「開啟一扇門」的遞迴例子來解釋遞迴並不準確,例子只描述了遞迴的一種情況。而「遞迴就是有去(遞去)有回(歸來)」的論斷同樣不夠準確。要為唯讀了文章前半部分的讀者惋惜了。我也給出自己對遞迴思想的總結吧:

遞迴的基本思想是廣義地把規模大的問題轉化為規模小的相似的子問題或者相似的子問題集合來解決。廣義針對規模的,規模的縮小具體可以是指遞迴函式的引數,也可以是其引數之一。相似是指解決大問題的方法和解決小問題的方法往往是同乙個方法,還可以是指解決子問題集的各子問題的方法是同乙個方法。解決大問題的方法可以是由解決次規模問題的方法和解決剩餘部分的方法組成,也可以是由一系列解決次規模問題的方法組成。

怎麼理解遞迴

遞迴最經典的例子就是 從前有座山,山里有座廟,廟裡有個老和尚,正在給小和尚講故事呢!故事是什麼呢?從前有座山,山里有座廟,廟裡有個老和尚,正在給小和尚講故事呢!故事是什麼呢?從前有座山,山里有座廟,廟裡有個老和尚,正在給小和尚講故事呢!故事是什麼呢?遞迴需要幾個條件 1,遞迴必須 要有邊界條件,也就...

python遞迴怎麼理解 理解遞迴 python

幾個小例子來理解遞迴 一 先來一點基礎的認識 1 遞迴是乙個不斷的將乙個問題分成更小的子問題最終找到乙個簡單的基礎問題,最後再由基礎問題的解決逐步向上解決初始問題的過程。所以不難看出,遞迴其實是分為兩部分的乙個是向下的遞推過程,另乙個就是向上的回溯過程。2 從上面我們已不難發現,在這個過程中,是存在...

遞迴演算法理解

遞迴演算法看起來比較簡單,當總覺得沒能領會到它的精髓,平常也沒可以使用它。今天看到這篇文章,說的比較透徹 1,遞迴與迴圈之間的關係 看過這樣一道題,問,程式結構化設計的三種基礎結構,順序 選擇 迴圈是不是必須的?當然,你知道這樣乙個論斷,只要有這三種就足夠了 但是能不能更少呢?答案是 可以 原因就是...