日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

backtrack-回溯搜索算法总结

發(fā)布時(shí)間:2023/12/10 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 backtrack-回溯搜索算法总结 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

backtrack——回溯算法總結(jié)

這幾天著重在刷LeetCode有關(guān)回溯搜索算法的題,之前也寫了一些博客,感覺當(dāng)時(shí)清楚,但是原理上還是有點(diǎn)模糊。之前根據(jù)別人的模板,依葫蘆畫瓢,解決了一些問題,但是有的時(shí)候條件變了,就有點(diǎn)理不清楚了,特別是哪里該加一些限制條件,很懵逼。所以總結(jié)了一下。

1. 到底什么是回溯?

回溯算法,都知道是基于遞歸的算法。那為什么要用遞歸呢,可以用傳統(tǒng)的寫法代替嘛?之所以用遞歸,就是因?yàn)槿绻脗鹘y(tǒng)的方式,很難寫或者根本寫不出來。舉個(gè)例子,比如我們想知道用集合nums = [1, 2, 3]中的三個(gè)數(shù)字(可重復(fù))一共能構(gòu)成多少個(gè)不同的三位數(shù),學(xué)過排列組合的都知道一共有27(3的3次方)種:(1,1,1), (1,1,2), (1,1,3), (2,1,1), (2,1,2), (2,1,3)…(3,3,3) 。用最傳統(tǒng)的方式,都會(huì)寫,用一個(gè)三層的for循環(huán)來寫:

vector<vector<int>> res; vector<int> path; for (int i = 0; i < 3; i++) {for (int j = 0; j < 3; j++) {for (int k = 0; k < 3; k++) {path.push_back({ nums[i], nums[j], nums[k] });res.push_back(path);}} }

這個(gè)例子中,集合中的元素還很少。那么如果集合中有100個(gè)元素呢?傳統(tǒng)方式是不是要寫100層循環(huán)?1000呢?因此,這種情況下單靠循環(huán)是完成不了的。這種情況下,就需要遞歸出場了。上面的代碼可以寫為如下遞歸的形式:

vector<vector<int>> res; vector<int> path; void backtrack_0(vector<int>& nums, vector<vector<int>> &res) {if (path.size() == nums.size()) {res.push_back(path);return;}// elsefor (int i = 0; i < nums.size(); i++) {path.push_back(nums[i);backtrack_0(nums, res);path.pop_back();} }

上面的代碼中,path的長度其實(shí)就是循環(huán)的深度,回溯遞歸里的每一層其實(shí)都是一個(gè)循環(huán);而else部分,則相當(dāng)于每層循環(huán)的方式(每層for循環(huán)該怎么寫)。遞歸其實(shí)就模擬了上訴過程。


如果題目變成了三個(gè)數(shù)字加起來能構(gòu)成不同的和的情況有多少(就是前面用過的數(shù),后面不能再用。比如:112和211的和就是一樣的)?那么該怎么改呢?
傳統(tǒng)的寫法:

for (int i = 0; i < 3; i++) {for (int j = i; j < 3; j++) {for (int k = j; k < 3; k++) {path.push_back({ nums[i], nums[j], nums[k] });res.push_back(path);}} }

對應(yīng)的遞歸寫法:

vector<vector<int>> res; vector<int> path; void backtrack_1(vector<int>& nums, vector<vector<int>> &res, int idx) {if (path.size() == nums.size()) {res.push_back(path);return;}// elsefor (int i = idx; i < nums.size(); i++) {path.push_back(nums[i);backtrack_1(nums, res, i);path.pop_back();} }

最后的輸出都一樣:[1, 1, 1], [1, 1, 2], [1, 1, 3], [1, 2, 2], [1, 2, 3], [1, 3, 3], [2, 2, 2], [2, 2, 3], [2, 3, 3], , [3, 3, 3]。
同時(shí),從這里可以看到:循環(huán)的起始范圍變了:從0變成了上層循環(huán)的循環(huán)變量;而在回溯函數(shù)中,循環(huán)的起始值也從0變?yōu)榱?strong>idx。說明,回溯跟多層循環(huán)有著非常密切的關(guān)系!終止條件跟循環(huán)層數(shù)有關(guān)系,遞歸函數(shù)里面的循環(huán)跟每層循環(huán)又有著非常緊密的聯(lián)系!

總結(jié)

以上是生活随笔為你收集整理的backtrack-回溯搜索算法总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。