【AcWing19】【LeetCode】DFS - 46/47/39/77/78/216/17/131/93/90/491
生活随笔
收集整理的這篇文章主要介紹了
【AcWing19】【LeetCode】DFS - 46/47/39/77/78/216/17/131/93/90/491
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- 代碼隨想錄在B站的視頻講得比AcWing好
- 模板題1:排列數字
- 模板題2:n皇后
- 方法一
- 方法二
- LeetCode 46. 全排列
- LeetCode 47. 全排列 II (重復元素)
- LeetCode 39. 組合總和
- LeetCode 77. 組合
- LeetCode 78. 子集
- LeetCode 216. 組合總和 III
- LeetCode 17. 電話號碼的字母組合
- LeetCode 131. 分割回文串
- LeetCode 93. 復原 IP 地址(還沒太學懂)
- LeetCode 90. 子集 II
- LeetCode 491. 遞增子序列
代碼隨想錄在B站的視頻講得比AcWing好
模板題1:排列數字
// 按行單個搜索 #include <iostream> using namespace std; const int N = 7; int n; int path[N]; //保存路徑,定義一個數組path[N] 來保存當前的路徑/模擬DFS的過程,當這個數組數字填滿的時候,就把當前的排列數字輸出出來 bool st[N]; //用于記錄該店是否來過 反正dfs重新進入void dfs(int u) { //u表示層數,u從0開始if (u == n) { //當數填滿n位數時 輸出n位數 并且換行for (int i = 0; i < n; i ++) { printf("%d ", path[i]);} puts("");return ;}for (int i = 1; i <= n; i ++) { if (!st[i]) { //如果這個位置空的話(沒有來過)path[u] = i;// u從0開始st[i] = true; //填數的時候記錄一下dfs(u + 1); //訪問下一層,u變成1st[i] = false; //回溯的時候 恢復現場[]}} }int main () {cin >> n;dfs(0); //這個題直接遍歷return 0; }模板題2:n皇后
方法一
#include<iostream> #include<cstdio> #include<algorithm> using namespace std;const int N = 10;char g[N][N]; int n; bool col[N], dg[N], udg[N]; // 用于標記每一列、正對角線、負對角線是否占用// u 表示第u行 void dfs(int u) { if(u == n){for(int i = 0; i < n; i++) puts(g[i]);// puts輸出二維數組 輸出每一行如何就會自動換行puts(""); return ; } // u表示行,從0開始計算,i表示第i列 // 按行枚舉 因為每一行都需要放皇后 相當于剪枝了// 剪枝(提前判斷當前方案已經錯誤,不再繼續往下搜索,提高算法效率) // 判斷皇后能否放在這格for(int i = 0; i < n; i++){// u表示行,i表示列,u+i表示正對角線的編號,i-u+n表示負對角線編號 // col[i]=false:第u層的第i列沒有皇后// dg[u+i]=false:u是外層遞歸,i是內層循環,i從0開始試,第u層的第u+i列沒有皇后if(!col[i] && !dg[u+i] && !udg[i-u+n]){g[u][i] = 'Q'; // 都不沖突的話,就把一個皇后放到這里 col[i] = dg[u+i] = udg[i-u+n] = true; // 表示該列、對角線被占用 dfs(u+1); //下一行g[u][i] = '.'; col[i] = dg[u+i] = udg[i-u+n] = false; // }} }int main() {scanf("%d", &n);// 初始化gfor(int i = 0; i < n; i++) for(int j = 0; j < n; j++)g[i][j] = '.';dfs(0); return 0; }方法二
#include <iostream> using namespace std; const int N = 20;//對角線元素 2n-1 取20防止越界 int n; char g[N][N]; //存儲圖 bool row[N],col[N], dg[N], udg[N]; //udg 副對角線 / //英語單詞 column 列 diagonal 主角線 \ //row 行void dfs (int x,int y,int s) { //xy為坐標 (x,y) s為 n皇后放置個數if (y == n) { //當x走到行末尾的時候 y = 0; //轉到下一行的第一個x++;}if (x == n) { //走到最后一行 且n皇后都放好的時候if (s == n) { // 如果找到方案的話for (int i = 0; i < n; i ++) {puts(g[i]);//puts輸出二維數組 輸出每一行如何就會自動換行 }//puts遍歷字符串這個語法不懂看下puts("");}return; //返回調用函數進行執行}dfs(x, y + 1, s);//不放皇后 并且訪問右節點// 判斷皇后能否放在這格if (!row[x] && !col[y] && !dg[x + y] && !udg[x - y + n]) {g[x][y] = 'Q';//放皇后 然后把row[x] = col[y] = dg[x + y] = udg[x - y + n] = true;dfs(x , y + 1, s + 1);//放置皇后,找下一層的//回溯的時候 記得恢復現場 ↓ row[x] = col[y] = dg[x + y] = udg[x - y + n] = false; g[x][y] = '.';} }int main () {cin >> n;for (int i = 0; i < n;i ++) {for (int j = 0; j < n; j ++) {g[i][j] = '.'; //初始化全部空格子}}dfs(0,0,0); //從第一行開始找return 0; }LeetCode 46. 全排列
class Solution { public:vector<vector<int>> result; // 存放路徑集合vector<int> path; // 存放單個路徑void backtracking (vector<int>& nums, vector<bool>& used) {// 此時說明找到了一組if (path.size() == nums.size()) {result.push_back(path);return;}//當路徑大小沒裝滿時for (int i = 0; i < nums.size(); i++) {if (used[i] == true) continue; // path里已經收錄的元素,直接跳過used[i] = true; // 把i位置的元素做標記path.push_back(nums[i]); //把i位置的元素加入路徑中backtracking(nums, used); // 對剩下的元素進行重排path.pop_back(); // 彈出當前元素,換另一個元素used[i] = false; // 回溯}}vector<vector<int>> permute(vector<int>& nums) {result.clear();path.clear();vector<bool> used(nums.size(), false);backtracking(nums, used);return result;} };作者:carlsun-2 鏈接:https://leetcode.cn/problems/permutations/solution/dai-ma-sui-xiang-lu-dai-ni-xue-tou-hui-s-mfrp/ 來源:力扣(LeetCode) 著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。LeetCode 47. 全排列 II (重復元素)
class Solution { private:vector<vector<int>> result;vector<int> path;void backtracking(vector<int>& candidates, int target, int sum, int startIndex) {if (sum == target) {result.push_back(path);return;}// 如果 sum + candidates[i] > target 就終止遍歷for (int i = startIndex; i < candidates.size() && sum + candidates[i] <= target; i++) {sum += candidates[i];path.push_back(candidates[i]);backtracking(candidates, target, sum, i);sum -= candidates[i];path.pop_back();}} public:vector<vector<int>> combinationSum(vector<int>& candidates, int target) {result.clear();path.clear();sort(candidates.begin(), candidates.end()); // 需要排序backtracking(candidates, target, 0, 0);return result;} };作者:carlsun-2 鏈接:https://leetcode.cn/problems/combination-sum/solution/dai-ma-sui-xiang-lu-dai-ni-xue-tou-hui-s-7tum/ 來源:力扣(LeetCode) 著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。LeetCode 39. 組合總和
class Solution { private:vector<vector<int>> result;vector<int> path;void backtracking(vector<int>& candidates, int target, int sum, int startIndex) {if (sum == target) {result.push_back(path);return;}// 如果 sum + candidates[i] > target 就終止遍歷for (int i = startIndex; i < candidates.size() && sum + candidates[i] <= target; i++) {sum += candidates[i];path.push_back(candidates[i]);backtracking(candidates, target, sum, i);sum -= candidates[i];path.pop_back();}} public:vector<vector<int>> combinationSum(vector<int>& candidates, int target) {result.clear();path.clear();sort(candidates.begin(), candidates.end()); // 需要排序backtracking(candidates, target, 0, 0);return result;} };LeetCode 77. 組合
class Solution { private:vector<vector<int>> result; // 存放符合條件結果的集合vector<int> path; // 用來存放符合條件結果//startIndex 避免組合重復選取元素(2,1)和(1,2)重復,標記搜索起始位置void backtracking(int n, int k, int startIndex) {if (path.size() == k) { // 路徑元素滿足要求時候就可以往result里存儲該路徑result.push_back(path);return; // 返回 遞歸出口}// 每次從startIndex開始添加新元素//for (int i = startIndex; i <= n; i++) {for (int i = startIndex; i <= n - (k - path.size()) + 1; i++) { // 優化的地方,剪枝,// (k - path.size())是還需要選取元素的個數,// n - (k - path.size()) + 1是最后能選取的位置,超過了就不滿足選取K個元素的條件了path.push_back(i); // 處理節點,從i開始添加 backtracking(n, k, i + 1); // 遞歸path.pop_back(); // 回溯,撤銷處理的節點,i++,重新進入for循環}} public:vector<vector<int>> combine(int n, int k) {result.clear(); // 可以不寫path.clear(); // 可以不寫backtracking(n, k, 1);return result;} };LeetCode 78. 子集
class Solution { private:vector<vector<int>> result;vector<int> path;void backtracking(vector<int>& nums, int startIndex) {result.push_back(path); // 收集子集,要放在終止添加的上面,否則會漏掉自己if (startIndex >= nums.size()) { // 終止條件可以不加return;}for (int i = startIndex; i < nums.size(); i++) {path.push_back(nums[i]);backtracking(nums, i + 1);path.pop_back();}} public:vector<vector<int>> subsets(vector<int>& nums) {result.clear();path.clear();backtracking(nums, 0);return result;} };作者:carlsun-2 鏈接:https://leetcode.cn/problems/subsets/solution/dai-ma-sui-xiang-lu-78-zi-ji-hui-su-sou-6yfk6/ 來源:力扣(LeetCode) 著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。LeetCode 216. 組合總和 III
class Solution { private:vector<vector<int>> result; // 存放結果集vector<int> path; // 符合條件的結果void backtracking(int targetSum, int k, int sum, int startIndex) {if (sum > targetSum) { // 剪枝操作return; // 如果path.size() == k 但sum != targetSum 直接返回}if (path.size() == k) {if (sum == targetSum) result.push_back(path);return;}for (int i = startIndex; i <= 9 - (k - path.size()) + 1; i++) { // 剪枝sum += i; // 處理path.push_back(i); // 處理backtracking(targetSum, k, sum, i + 1); // 注意i+1調整startIndexsum -= i; // 回溯path.pop_back(); // 回溯}}public:vector<vector<int>> combinationSum3(int k, int n) {result.clear(); // 可以不加path.clear(); // 可以不加backtracking(n, k, 0, 1);return result;} };作者:carlsun-2 鏈接:https://leetcode.cn/problems/combination-sum-iii/solution/dai-ma-sui-xiang-lu-dai-ni-xue-tou-hui-s-petp/ 來源:力扣(LeetCode) 著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。LeetCode 17. 電話號碼的字母組合
class Solution { private:const string letterMap[10] = {"", // 0"", // 1"abc", // 2"def", // 3"ghi", // 4"jkl", // 5"mno", // 6"pqrs", // 7"tuv", // 8"wxyz", // 9}; public:vector<string> result;string s;void backtracking(const string& digits, int index) {if (index == digits.size()) {result.push_back(s);return;}int digit = digits[index] - '0'; // 將index指向的數字轉為intstring letters = letterMap[digit]; // 取數字對應的字符集for (int i = 0; i < letters.size(); i++) {s.push_back(letters[i]); // 處理backtracking(digits, index + 1); // 遞歸,注意index+1,一下層要處理下一個數字了s.pop_back(); // 回溯}}vector<string> letterCombinations(string digits) {s.clear();result.clear();if (digits.size() == 0) {return result;}backtracking(digits, 0);return result;} };作者:carlsun-2 鏈接:https://leetcode.cn/problems/letter-combinations-of-a-phone-number/solution/dai-ma-sui-xiang-lu-17-dian-hua-hao-ma-d-ya2x/ 來源:力扣(LeetCode) 著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。LeetCode 131. 分割回文串
class Solution { private:vector<vector<string>> result;vector<string> path; // 放已經回文的子串void backtracking (const string& s, int startIndex) {// 如果起始位置已經大于s的大小,說明已經找到了一組分割方案了if (startIndex >= s.size()) {result.push_back(path);return;}for (int i = startIndex; i < s.size(); i++) {if (isPalindrome(s, startIndex, i)) { // 是回文子串// 獲取[startIndex,i]在s中的子串string str = s.substr(startIndex, i - startIndex + 1);path.push_back(str);} else { // 不是回文,跳過continue;}backtracking(s, i + 1); // 尋找i+1為起始位置的子串path.pop_back(); // 回溯過程,彈出本次已經填在的子串}}bool isPalindrome(const string& s, int start, int end) {for (int i = start, j = end; i < j; i++, j--) {if (s[i] != s[j]) {return false;}}return true;} public:vector<vector<string>> partition(string s) {result.clear();path.clear();backtracking(s, 0);return result;} };作者:carlsun-2 鏈接:https://leetcode.cn/problems/palindrome-partitioning/solution/131-fen-ge-hui-wen-chuan-hui-su-sou-suo-yp2jq/ 來源:力扣(LeetCode) 著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。LeetCode 93. 復原 IP 地址(還沒太學懂)
class Solution { private:vector<string> result;// 記錄結果// startIndex: 搜索的起始位置,pointNum:添加逗點的數量void backtracking(string& s, int startIndex, int pointNum) {if (pointNum == 3) { // 逗點數量為3時,分隔結束// 判斷第四段子字符串是否合法,如果合法就放進result中if (isValid(s, startIndex, s.size() - 1)) {result.push_back(s);}return;}for (int i = startIndex; i < s.size(); i++) {if (isValid(s, startIndex, i)) { // 判斷 [startIndex,i] 這個區間的子串是否合法s.insert(s.begin() + i + 1 , '.'); // 在i的后面插入一個逗點pointNum++;backtracking(s, i + 2, pointNum); // 插入逗點之后下一個子串的起始位置為i+2pointNum--; // 回溯s.erase(s.begin() + i + 1); // 回溯刪掉逗點} else break; // 不合法,直接結束本層循環}}// 判斷字符串s在左閉又閉區間[start, end]所組成的數字是否合法bool isValid(const string& s, int start, int end) {if (start > end) {return false;}if (s[start] == '0' && start != end) { // 0開頭的數字不合法return false;}int num = 0;for (int i = start; i <= end; i++) {if (s[i] > '9' || s[i] < '0') { // 遇到非數字字符不合法return false;}num = num * 10 + (s[i] - '0');if (num > 255) { // 如果大于255了不合法return false;}}return true;} public:vector<string> restoreIpAddresses(string s) {result.clear();if (s.size() > 12) return result; // 算是剪枝了backtracking(s, 0, 0);return result;} };作者:carlsun-2 鏈接:https://leetcode.cn/problems/restore-ip-addresses/solution/dai-ma-sui-xiang-lu-93-fu-yuan-ip-di-zhi-pzjo/ 來源:力扣(LeetCode) 著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。LeetCode 90. 子集 II
class Solution { private:vector<vector<int>> result;vector<int> path;void backtracking(vector<int>& nums, int startIndex, vector<bool>& used) {result.push_back(path);for (int i = startIndex; i < nums.size(); i++) {// used[i - 1] == true,說明同一樹支candidates[i - 1]使用過// used[i - 1] == false,說明同一樹層candidates[i - 1]使用過// 而我們要對同一樹層使用過的元素進行跳過if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) {continue;}path.push_back(nums[i]);used[i] = true;backtracking(nums, i + 1, used);used[i] = false;path.pop_back();}}public:vector<vector<int>> subsetsWithDup(vector<int>& nums) {result.clear();path.clear();vector<bool> used(nums.size(), false);sort(nums.begin(), nums.end()); // 去重需要排序backtracking(nums, 0, used);return result;} };作者:carlsun-2 鏈接:https://leetcode.cn/problems/subsets-ii/solution/90-zi-ji-iiche-di-li-jie-zi-ji-wen-ti-ru-djmf/ 來源:力扣(LeetCode) 著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。LeetCode 491. 遞增子序列
class Solution { private:vector<vector<int>> result;vector<int> path;void backtracking(vector<int>& nums, int startIndex) {if (path.size() > 1) {result.push_back(path);// 注意這里不要加return,要取樹上的節點}unordered_set<int> uset; // 使用set對本層元素進行去重for (int i = startIndex; i < nums.size(); i++) {if ((!path.empty() && nums[i] < path.back())|| uset.find(nums[i]) != uset.end()) {continue;}uset.insert(nums[i]); // 記錄這個元素在本層用過了,本層后面不能再用了path.push_back(nums[i]);backtracking(nums, i + 1);path.pop_back();//uset不回溯,因為每次回溯都會定義一個新的set,這是與其他題目區別的地方}} public:vector<vector<int>> findSubsequences(vector<int>& nums) {result.clear();path.clear();backtracking(nums, 0);return result;} };總結
以上是生活随笔為你收集整理的【AcWing19】【LeetCode】DFS - 46/47/39/77/78/216/17/131/93/90/491的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎样学习AI-Adobe
- 下一篇: 关于插画师,大家不知道的“秘密”