回溯算法超详细讲解(附代码)
因?yàn)樽约涸趯W(xué)習(xí)回溯算法的時(shí)候一直不清楚回溯的具體過(guò)程, 可能是因?yàn)樽约禾?#xff0c;這個(gè)問(wèn)題困擾了我好幾天。回溯還是挺有用的,樹(shù)的遍歷,全排列問(wèn)題都可以用回溯算法解。面試的時(shí)候好像也比較側(cè)重回溯算法和動(dòng)態(tài)規(guī)劃。
回溯形象解釋下:假設(shè)你要從你家去你女朋友家,沒(méi)有導(dǎo)航,但是她告訴你了,從你家到她家要只需經(jīng)過(guò)兩個(gè)十字路口就可以,這個(gè)時(shí)候怎么辦呢,只能是從第一個(gè)十字路口選擇一個(gè)方向(A)然后一直走遇到第二個(gè)十字路口,然后你又隨便選擇了一個(gè)方向(a)走,過(guò)了一會(huì)你打電話告訴女朋友你走的那條路周?chē)沫h(huán)境,然后你女友告訴你:死鬼那條路不對(duì),這個(gè)時(shí)候,只能回到第二個(gè)十字路口那選擇(b,c,d)方向,不幸的是你一開(kāi)始就選擇錯(cuò)了十字路口,四條路試完,只能回到第一個(gè)十字路口,再次選擇,最后,你把第一個(gè)十字路口的四個(gè)方向都試完,你一定能到女友家,然后一頓云雨,正當(dāng)你大汗淋淋的時(shí)候戛然而止,你說(shuō):媽的,我還有一道回溯算法的題沒(méi)做,回去做了。卒
玩笑歸玩笑,拿個(gè)具體的例子說(shuō)明一下。
這道題來(lái)源于leetcode
class Solution { public:vector<vector<int>> subsets(vector<int>& nums) {vector<vector<int> > res;vector<int> tmp;helper(res,tmp,nums,0);return res;}void helper(vector<vector<int> >& res,vector<int> &tmp,vector<int>& nums,int level){if(tmp.size()<=nums.size()){res.push_back(tmp);}for(int i=level;i<nums.size();i++){tmp.push_back(nums[i]);helper(res,tmp,nums,i+1);}tmp.pop_back();} };注:tmp一開(kāi)始為[] ,在后面寫(xiě)的時(shí)候不再說(shuō)寫(xiě)入tmp和res。
a):i=0 開(kāi)始 遞歸回溯 ,此時(shí)tmp里面有[1] 進(jìn)入helper后 res里面有 [1]?
b)i+1 變?yōu)? 注意這個(gè)i+1并不是for循環(huán)里面的i++,而是你遞歸里面的i+1。這是理解回溯算法的關(guān)鍵,因?yàn)椴皇莊or循環(huán)里面的i+1,所以for循環(huán)里面還有i=1,i=2沒(méi)用,相當(dāng)于十字路口的其他方向,回溯是回到這里,tmp變?yōu)閇1,2],res里面有[1][1,2]。
c)i+1 tmp:[1,2,3];res:[1][1,2][1,2,3];此時(shí)發(fā)現(xiàn)i=4不滿足for循環(huán)的條件,執(zhí)行tmp.pop_back()tmp為空。這個(gè)時(shí)候要回溯了,因?yàn)橐呀?jīng)走到路的盡頭了,回到最近的那個(gè)地方也就是b),此時(shí)我們發(fā)現(xiàn)2那個(gè)方向已經(jīng)走過(guò)了所以不再走,換另一個(gè)方向,即for循環(huán)中的i+1。也就是說(shuō)tmp不再插入2了,插入3變?yōu)閇1,3]。然后又滿足for循環(huán)了,執(zhí)行tmp.pop_back()tmp為空。此時(shí)? b)試完了,一共兩個(gè)方向,即i=1和i=2.然后回到? a) tmp :[2] res:[1][1,2][1,2,3],[1,3] [2]。以此類(lèi)推,應(yīng)該是可以明白了,到這里。
?
?
總結(jié)
以上是生活随笔為你收集整理的回溯算法超详细讲解(附代码)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: mysql data too large
- 下一篇: php golang 加密 对接,把ph