感性理解遞迴搜尋(dfs)
阿新 • • 發佈:2019-01-09
遞迴絕對是我最最最討厭的東西,沒有之一,所以我現在是懷著百感交集的心情在寫這篇部落格,然而最糾結的是我現在無從下手。
為了表示歉意,我也不知道從哪裡開始,就想到什麼些什麼吧
第一步:理解遞迴搜尋的概念
- 遞迴搜尋是一個麻煩又複雜的東西,但是卻是一個不得不學懂的演算法
- 函式有很多種形式,在搜尋中通常是dfs,反正我講的是dfs,也就是呼叫自己的函式
- 要想搜尋快,就得學剪枝
- 搜尋不僅僅是搜尋,還有害死人的回溯,這個我覺得是搜尋當中最容易搞亂的
- 對了對了,還有邊界的定義,搜尋因為是深搜所以要時間長,如果邊界是錯誤就麻煩了
- 最後一點就是在搜尋當中
絕對不是返回到主函式,而是返回到上一個遞迴中
第二步:分開理解
概念性的大概的我記得的東西我都講了,剩下的就一點一點來解剖,
哈哈哈哈哈!!!
- 遞迴為什麼麻煩複雜卻一定要學呢?因為遞迴是一個很廣泛的東西,遞迴函式的發明絕對是世界上最偉大的發明之一,換個角度想想,如果沒有遞迴自己呼叫自己的話,那就意味著我們要用無數的迴圈來實現,
媽呀想想就可怕,時間久不說,打起來也麻煩。所以說,函式中的dfs函式,bfs函式都是很偉大的東西,就算在不懂,也要學,所以,與其被逼迫著學,還不如開開心心的看著我的部落格來學。- 函式是很多很多的,但是搜尋用的函式,尤其是深搜就是用dfs,dfs我覺得最最最特別的就是這是一個呼叫自己的函式。呼叫自己是什麼意思呢?就是說我們在迴圈當中的時候,如果我們迴圈到的是還沒有使用過的,就可以使用,下次的時候我們就是以這個為上層來展開遞迴,這就叫做呼叫自己,一次一次以自己為上層來遞迴自己下面符合條件的。
- 搜尋,要是稍微低階一點理解,就是迴圈,所以我們應該把一切浪費時間的搜尋都刪掉,保證搜尋的簡單,剪枝就是最最最重要的,剪枝的方法很多很多,但是這不是我們主要講的,所以如果看到這裡的小可愛們,可以看看我之前寫過的對剪枝的深刻理解的部落格(可能會有點花裡胡哨,但是我是為了區分開一個個模組),感性理解深搜剪枝
- 搜尋搜尋搜尋,為什麼叫搜尋?就像我們地震之後的搜救,是不是要一遍遍搜尋搜尋,一遍遍排除,這裡也是如此,我們找到了一個沒有搜尋過的時候,我們就要標記為搜尋過之後,就進入搜尋,然後經過搜尋過程之後,回到了原位,就要把這個位置標記為沒有搜尋過。為什麼呢?因為一遍的搜尋,你能保證全對嗎?顯然不能,所以我們要把我們折騰過佔用過的資源給釋放出去,萬一下次再次搜尋的時候,可以用,這個從被標記搜尋過到被標記沒搜尋過的過程叫做回溯。
- 還有一點小可愛,就是邊界的問題,為什麼我要講這個呢?因為這個關乎到我們以後做其他題目的一個技巧,不管做什麼題審題是最最最最關鍵的,如果你的題目沒有審清楚,很抱歉,這道題你想一百年都想不出來。恰恰這個題目就隱藏了我們的邊界的一個問題,舉個現實的例子,題目中的資料範圍是不是我們定義陣列的一個依據。再舉一個例子,比如就拿生日蛋糕這一題來說,如果我們沒有審清楚題目中的當前這一層的半徑比上一層半徑至少多1,那我們就不會知道這個最底層的半徑至少是m,所以這就是審題,也就是找邊界的最重要的一個方面,一個好的開頭是成功的一半。還有一點就是我歸納的,如果你的邊界找錯了,意味著什麼?意味著這道題你有百分之十的可能性是做對的,百分之四十是半對,百分之五十是全錯。
- 最後一點,就是我今天才算真正搞懂的一個東西,就是那個遞迴當中。這個,注意一下,不是返回到主函式,而是返回到進入這一層遞迴的那一層遞迴。我畫圖來解釋吧。
- 看完圖的看到這裡來, 很好很好,就是說看完了對吧。首先我們把這個該死的遞迴想成一棵樹,然後我們的這棵樹有好多個子狀態,這些子狀態其實就是自己呼叫自己之後的遞迴,既然是呼叫的,那我們返回答案的時候就要返回到自己的上層,所以我們才會用return,因為我們找到的還不是最優的,只是當前可以遞迴的這個函式的一個值而已,最優的答案還是要最上面的那一層ok,也就是我們的主函式當中進入的這個遞迴的值才是最終答案。還有一個估計就是,因為是遞迴篩選,所以如果有3個子狀態的話,不是最早到達的為最優的,而是經過比較之後的才是最優的,這個可以理解了吧。
- 好啦,我們終於把遞迴講清楚了對吧。
最後總結一下吧
- 邊界啊邊界
- 剪枝啊剪枝
- 回溯啊回溯
- 返回啊返回
好啦,到此結束,加油哦,我下一次可能就是講寬搜,也就是廣搜了。