第77题. 组合
链接:代码随想录
class Solution { public: vector<vector<int>> v; vector<int>res; vector<vector<int>> combine(int n, int k) { backtracing(n,1,k); return v; } void backtracing(int n,int startIndex,int k) { if(res.size()==k) { v.push_back(res); //res.clear(); return; } for(int j=startIndex;j<=n;j++) { res.push_back(j); backtracing(n,j+1,k); res.pop_back(); } } };
剪枝:
class Solution { public: vector<vector<int>> v; vector<int>res; vector<vector<int>> combine(int n, int k) { backtracing(n,1,k); return v; } void backtracing(int n,int startIndex,int k) { if(res.size()==k) { v.push_back(res); //res.clear(); return; } for(int j=startIndex;j<=n - (k - res.size()) + 1;j++) { res.push_back(j); backtracing(n,j+1,k); res.pop_back(); } } };
216. 组合总和 III
链接:力扣
剪枝注意:
class Solution { public: vector<vector<int>>v; vector<int>res; vector<vector<int>> combinationSum3(int k, int n) { backtracing(k,n,1); return v; } void backtracing(int k,int n,int startIndex) { if(res.size()==k && n==0) { v.push_back(res); } for(int j=startIndex;j<=9-(k-res.size())+1;j++) { res.push_back(j); if(n-j>=0) { backtracing(k,n-j,j+1); } res.pop_back(); } } };
a
17.电话号码的字母组合
链接:力扣
自己的做法:
class Solution { public: vector<string>v; vector<string>res; string str; vector<string> letterCombinations(string digits) { if(digits=="") { return v; } v.push_back("abc"); v.push_back("def"); v.push_back("ghi"); v.push_back("jkl"); v.push_back("mno"); v.push_back("pqrs"); v.push_back("tuv"); v.push_back("wxyz"); backtracing(v,0,digits); return res; } void backtracing(vector<string> &v,int digitsIndex,string &digits) { if(digitsIndex==digits.size()) { res.push_back(str); } else { string s=v[digits[digitsIndex]-'2']; cout<<s<<endl; for(int j=0;j<s.size();j++) { str.push_back(s[j]); backtracing(v, digitsIndex+1,digits); str.pop_back(); } } } };
a
39. 组合总和
链接:代码随想录
class Solution { public: vector<vector<int>>v; vector<int>res; vector<vector<int>> combinationSum(vector<int>& candidates, int target) { int n=candidates.size(); if(n==0) { return v; } backtracing(candidates,target,0,n); return v; } void backtracing(vector<int> & candidates,int target,int startIndex,int n) { if(target==0) { v.push_back(res); } for(int j=startIndex;j<n;j++) { if(target-candidates[j]>=0) { res.push_back(candidates[j]); backtracing(candidates,target-candidates[j],j,n); res.pop_back(); } } } };
40.组合总和II
链接:代码随想录
class Solution { public: vector<vector<int>> v; vector<int>res; vector<vector<int>> combinationSum2(vector<int>& candidates, int target) { int n=candidates.size(); if(n==0) { return v; } sort(candidates.begin(),candidates.end()); backtracing(candidates,target,0,n); return v; } void backtracing(vector<int>& candidates, int target,int startIndex,int n) { if(target==0) { v.push_back(res); } for(int j=startIndex;j<n;j++) { if(j>startIndex && candidates[j]==candidates[j-1]) { continue; } if(target-candidates[j]>=0) { res.push_back(candidates[j]); backtracing(candidates,target-candidates[j],j+1,n); res.pop_back(); } } } };
a
131.分割回文串
链接:力扣
自己的解法,欣喜若狂的做对了
class Solution { //牢记分割回文串这道题是回溯 //牢记是组合问题,而且startIndex就是隔板 public: vector<vector<string>> v; vector<string>res; vector<vector<string>> partition(string s) { int n=s.size(); if(n==0) { return v; } backtracing(s,0,n); return v; } void backtracing(string s,int startIndex,int n) { if(startIndex==n) { v.push_back(res); } for(int j=startIndex;j<n;j++) { string str=s.substr(startIndex,j-startIndex+1); if(is_huiwen(str)) { res.push_back(str); backtracing(s,j+1,n); res.pop_back(); } } } bool is_huiwen(string &str) { int right=str.size()-1; int left=0; while(left<right) { if(str[left]!=str[right]) { return false; } left++; right--; } return true; } };
93.复原IP地址
链接:代码随想录
挺震惊的,我写的还挺快的
class Solution { public: vector<string>v; //string res=""; vector<string> restoreIpAddresses(string s) { backtracing(s,0,s.size(),0,""); return v; } void backtracing(string &s,int startIndex,int n,int k,string res)//k代表已经加入的一个小数点个数 { if(startIndex==n && k==4) { res.pop_back(); v.push_back(res); } for(int j=startIndex;j<n;j++) { string str=s.substr(startIndex,j-startIndex+1); if(str.size()>1 && str[0]=='0') { continue; } if(str.size()<=3) { int num=atoi(str.c_str()); if(num>=0 && num<=255) { backtracing(s,j+1,n,k+1,res+str+"."); } } } } };
a
78. 子集
链接:代码随想录
吓人。。。。今天的代码都是一次对
代码:
class Solution { public: vector<vector<int>> v; vector<int>res; vector<vector<int>> subsets(vector<int>& nums) { int n=nums.size(); backtracing(nums,0,n); return v; } void backtracing(vector<int>& nums,int startIndex,int n) { if(res.size()<=n ) { v.push_back(res); } for(int j=startIndex;j<n;j++) { res.push_back(nums[j]); backtracing(nums,j+1,n); res.pop_back(); } } };
a
a
90. 子集 II
链接:力扣
还是那套模板
class Solution { public: vector<vector<int>>v; vector<int>mv; vector<vector<int>> subsetsWithDup(vector<int>& nums) { sort(nums.begin(),nums.end()); backtracing(nums,0); return v; } void backtracing(vector<int> &nums,int startIndex) { if(mv.size()<=nums.size()) { v.push_back(mv); } for(int j=startIndex;j<nums.size();j++) { if(j>startIndex && nums[j]==nums[j-1]) { continue; } mv.push_back(nums[j]); backtracing(nums,j+1); mv.pop_back(); } } };
491.递增子序列 ---------没思路
链接:代码随想录
看了答案,主要是横向扩展节点时要做约束
答案:
46.全排列 ----------------------写错,排列掌握的没有组合好
链接:代码随想录
错误写法:我也不知道咋发明的,还是理解上错误,貌似我这样写约束的是纵向,打印结果只有一种。但是正确解法是每个节点上横向扩展,比如【1,2,3】第一层已经选了1,那么就平等的试一下选2、选3,选完就used,也就是节点上横向扩展。
所以
class Solution { public: vector<bool>used; vector<vector<int>>v; vector<int>res; vector<vector<int>> permute(vector<int>& nums) { int n=nums.size(); used.resize(n,false); backtracing(nums,0,n); return v; } void backtracing(vector<int>&nums,int i,int n) { if(i==n) { v.push_back(res); } for(int j=0;j<n;j++) { if(!used[j]) { used[i]=true; res.push_back(nums[i]); backtracing(nums,i+1,n); res.pop_back(); used[i]=false; } } } };
正确答案:
class Solution { public: vector<bool>used; vector<vector<int>>v; vector<int>res; vector<vector<int>> permute(vector<int>& nums) { int n=nums.size(); used.resize(n,false); backtracing(nums,n); return v; } void backtracing(vector<int>&nums,int n) { if(res.size()==n) { v.push_back(res); } for(int j=0;j<n;j++) { if(!used[j]) { used[j]=true; res.push_back(nums[j]); backtracing(nums,n); res.pop_back(); used[j]=false; } } } };
a
47.全排列||
class Solution { public: //关键词:可包含重复数字的序列 nums的排列问题 //排列:一定用到used数组。而且每一层都从0开始遍历,遍历used数组中未标记的 //可重,要先排序,对于横向展开的选择再去重,和组合思路一样 vector<vector<int>>v; vector<int>mv; vector<vector<int>> permuteUnique(vector<int>& nums) { v.clear(); mv.clear(); vector<bool>used; used.resize(nums.size(),false); sort(nums.begin(),nums.end());//先排序再去重 backtracing(nums,used); return v; } void backtracing(vector<int> &nums,vector<bool> &used) { if(mv.size()==nums.size()) { v.push_back(mv); } for(int j=0;j<nums.size();j++) { if (j > 0 && nums[j] == nums[j - 1] && used[j- 1] == false) { continue; } if(used[j]==false) { used[j]=true; mv.push_back(nums[j]); backtracing(nums,used); mv.pop_back(); used[j]=false; } } } };
51. N皇后
链接:代码随想录
class Solution { public: vector<vector<string>>v; vector<string>board; vector<vector<string>> solveNQueens(int n) { board.resize(n,string(n,'.')); backtracing(board,0,n); return v; } void backtracing(vector<string>&board,int i,int n) { if(i==n) { v.push_back(board); } for(int j=0;j<n;j++) { if(if_can(board,i,j,n)) { board[i][j]='Q'; backtracing(board,i+1,n); board[i][j]='.'; } } } bool if_can(vector<string>&board,int i,int j,int n) { //不同列 for(int k=0;k<i;k++) { if(board[k][j]=='Q') { return false; } } //左上角检查 int x=i; int y=j; while(x>=0 && y>=0&&x<n &&y<n) { if(board[x][y]=='Q') { return false; } x--; y--; } x=i; y=j; //右上角检查 while(x>=0 && y>=0&&x<n &&y<n) { if(board[x][y]=='Q') { return false; } x--; y++; } return true; } };
52. N 皇后 II-----应该没啥问题
链接:力扣
class Solution { public: //记录之前的Q的位置; vector<pair<int,int>>location; int cnt=0; int totalNQueens(int n) { backtracing(0,n); return cnt; } void backtracing(int i,int n) { if(i==n) { cnt++; } for(int j=0;j<n;j++) { if(if_can(i,j,n)) { location.push_back({i,j}); backtracing(i+1,n); location.pop_back(); } } } bool if_can(int i,int j,int n) { //同一列 for(auto p:location) { //同一列 if(p.second==j) { return false; } //左上角 //右上角 if(((i-p.first)==(j-p.second))|| ((i-p.first)==(p.second-j)) ) { return false; } } return true; } };
37. 解数独
链接:代码随想录
大概看了一下答案,重点在于三次循环。
错了一些,重点是回溯是一个bool,找到合适的立即返回结果,不合适的不返回。这样能防止超时。
class Solution { public: void solveSudoku(vector<vector<char>>& board) { int n=board.size(); int m=board[0].size(); backtracing(board,n,m); } bool backtracing(vector<vector<char>>&board,int n,int m) { for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { if(board[i][j]!='.') { continue; } for(int k='1';k<='9';k++) { if(is_Valid(i,j,k,board)) { board[i][j]=k; if (backtracing(board,n,m)) return true; // 如果找到合适一组立刻返回 board[i][j]='.'; } } return false; // 9个数都试完了,都不行,那么就返回false } } return true; } bool is_Valid(int i,int j,char ch,vector<vector<char>>&board) { //同一列,检查 for(int t=0;t<9;t++) { if(board[t][j]==ch) { return false; } } //同一行,检查 for(int t=0;t<9;t++) { if(board[i][t]==ch) { return false; } } int n=i/3; int m=j/3; for(int t=n*3;t<n*3+3;t++) { for(int k=3*m;k<3*m+3;k++) { if(board[t][k]==ch) { return false; } } } return true; } };