遞迴的二三事

2022-01-23 11:27:29 字數 2886 閱讀 8155

斐波那契數列,大家都很熟悉了,從第三項開始,就是把前面兩項之和加起來等於第三項,很多人也知道這道題目用遞迴來可以解,也很多人可以馬上順利的寫出遞迴**,但是如果你多問一句也許他們就懵逼了,叫他們說一下對遞迴的理解,或者說斐波那契數列能有什麼改進的地方。

很多人都知道斐波那契數列,漢諾塔問題要用遞迴,也許**也可以寫出來(很多時候都是基於他們記憶寫的),下面我就說說我自己對遞迴的理解。 遞迴:遞就是傳遞,歸就是回來的意思,我們生活中可能也有很多這樣的例子,比如你和女朋友去電影院看電影,你想知道自己是坐在第幾排(由於太黑了,看不清前面的排樹),這個時候,你可能想到乙個辦法:就是問前面的人是坐第幾排(前面的人也不知道自己是做第幾排,就再問前面的人,前面的人再問前面的人,直到第一排),這就是遞的過程,前面第一排的告訴第二排的,再到第三排...最後到你自己(這就是歸的過程),這就是遞迴。

我在剛剛學習遞迴的時候,我也花了很大心思才搞懂斐波那契數列數列是怎麼理解的。我一開始是這麼想的,f(40)=f(39)+f(38)  f(39)=f(38)+f(37)...一直這樣想,想下去頭都大了。我這種想法呢,就是很經典的陷入了遞迴的思維誤區。其實正確的思考方式應該是,對於遞迴來說:如果乙個問題a可以分解為多個子問題b,c,d 。然後b,c,d又可以分為子問題b1,b2,c1,c2...。當我們要求a的時候,應該要假設b,c,d都是已知(千萬別一層層的往下想子問題和子子問題的關係),要遮蔽掉遞迴細節,這樣理解起來就簡單很多了。

1、可以把乙個問題分為子問題,分治法。

2、每個小問題的求解方式和大問題的求解方式應該是一樣的(除了資料規模不一樣)

3、還要有中止條件,不能無限遞迴下去。

很多面試官都會問,你在平時工作中,有哪些地方用到了遞迴,我就舉幾個例子,1、遍歷資料夾裡面的所有問題並輸出(包含子資料夾和子資料夾)。2、常見的樹形結構資料(選單,地區,部門,這種有層級關係的,一般會用遞迴來求解子節點)3、斐波那契數列,漢諾塔問題(這個就工作應該問不到用來加深自己對遞迴的理解)4、快速排序,樹的遍歷等等都可以用到遞迴,如果你告訴面試官,你沒用過遞迴,你就gg啦(壞笑)。

問題1:遍歷資料夾裡面的所有問題並輸出(包含子資料夾和子資料夾)

///

///獲取資料夾下面的所有檔案

/// ///

///static list getfilesbydir(directoryinfo dir,listfileinfos)

foreach (var subdir in

dir.getdirectories())

foreach(var subfile in

dir.getfiles())

return

fileinfos ;

}

問題2:常見的樹形結構(地區樹)

//

上面是模擬資料庫的資料。 現在要求的是廣東省下的子節點(假設是乙個無限層級,雖然案例的資料只有三層)

//要解決這個問題,為什麼想到用遞迴呢,因為求乙個廣東省的子節點和求廣東省下面的韶關市的子節點套路是一樣的。

//我要返回一棵樹形的結構

public listgetregions(string

parentcode)

).tolist();

foreach (var subregion in

parentregions)

return

parentregions;

}

問題3:斐波那契數列

斐波那契數列,從第三項開始,值為前面兩項的和。求解方式如下

public

int fibonaccioridionary(int

n)

return fibonaccioridionary(n - 1) + fibonaccioridionary(n - 2

); }

問題4:漢諾塔問題

漢諾塔問題呢,可以這樣考慮,當只有乙個盤的時候呢,就是直接從a移動到c。當你有兩個盤的時候,先把乙個盤從a移動到b,再把乙個盤從a移動到c,再把剩下的從b移動到c。當有10個盤的時候,套路也是一樣的,你可以假設另外99個盤是已經移動到b了的(把它當成兩個盤來看待)。

static

void hannuota(int n,char a,char b,char

c)

else

}static

void move(char a,char

b) 移動到");

}

上面**都可以在github這裡:

說起遞迴的缺點,可能很多時候,我們調著的時候,可能就會報乙個堆疊溢位的錯誤。其實這個就是因為,我們函式在記憶體中是堆疊的形式存在的,函式執行的時候,會把臨時變數等等壓入棧中,執行完畢後,再把他們彈出棧(因為每個函式棧的大小是有限的,所以就導致堆疊溢位了)。

遞迴還有一點就是很多重複的計算,比如計算斐波那契數列,f(50)=f(49)+f(48)  f(49)=f(48)+f(47) ,這其中f(48)就是重複計算了,所以我們要盡可能的避免重複計算。

斐波那契數列的改進做法如下(加個hash表來儲存中間的值,避免重複計算):

public

int fibonacciimprove(int

n)

if(_hashdict.containskey(n))

int res = fibonacciimprove(n - 1) + fibonacciimprove(n - 2

); _hashdict.add(n, res);

return

res;

}

至於堆疊溢位的話,只能通過限制遞迴深度來進行。當遞迴深度大於指定值的時候,報錯。

上面**都可以在github這裡:

埠二三事

最近在看0 1024熟知埠所對應的內容,然後寫了指令碼對iana資料庫所提供的埠和服務對應的關係進行了歸類,發現如下的埠是值得注意的地方。就在處理0 1024埠的時候,出現的值得注意的地方列舉如下。總的來說,有些埠已經加入了對sctp以及dccp的支援。sctp和dccp可以看成分別是對tcp和ud...

今日二三事

上午早起去辦租賃備案,辦完了回來啟用了信用卡並稍微摸索了下,中午和室友一起訂烤魚和小龍蝦,吃完都十二點多,午睡未睡著看了一會漫畫和 去書房三點多,買了一杯咖啡,看看一些前端文章,狀態好的情況下還是可以看進去一些英文文件的。晚飯後繼續看,邊看邊跟老弟聊天,他最近要學python,我打算也學一學,順便帶...

生活二三事

今天遭遇了一系列的事情,這些事情用當前的我個人的認知來說算是衰事吧,乙個倒也見怪不怪,但今天的接憧而至的架勢的的確確給我挫折感。然後呢我不得不散了會步,按照平時的狀態我是極其不喜歡乙個人散步的,因為那樣會感覺很孤獨,畢竟大學校園三五成群,兩兩相依的情景隨處可見,總以別人的眼光來看待自己很是累,恩。路...