class Solution {
public:
vector<int> path;
vector<vector<int>> res;
//确定递归函数参数和返回值
void backtracking(int n,int k,int startIndex){
//确定终止条件
if(path.size()==k){
res.push_back(path);
return;
}
//确定单层递归逻辑
for(int i=startIndex;i<=n;i++){
path.push_back(i);
backtracking(n,k,i+1);
path.pop_back();
}
}
vector<vector<int>> combine(int n, int k) {
backtracking(n,k,1);
return res;
}
};
剪枝优化:(对每层循环遍历的范围进行了缩小)
class Solution {
public:
vector<int> path;
vector<vector<int>> res;
//确定递归函数参数和返回值
void backtracking(int n,int k,int startIndex){
//确定终止条件
if(path.size()==k){
res.push_back(path);
return;
}
//确定单层递归逻辑
for(int i=startIndex;i<=n-(k-path.size())+1;i++){//优化的地方
path.push_back(i);
backtracking(n,k,i+1);
path.pop_back();
}
}
vector<vector<int>> combine(int n, int k) {
backtracking(n,k,1);
return res;
}
};
class Solution {
public:
vector<int>path;
vector<vector<int>>res;
//确定递归函数参数和返回值
void backtracking(int k,int n,int startIndex){
//确定终止条件
if(path.size()==k){
if(n==0){
res.push_back(path);
return;
}
}
//确定单层递归逻辑
for(int i=startIndex;i<=9;i++){
n-=i;
path.push_back(i);
backtracking(k,n,i+1);
path.pop_back();
n+=i;
}
}
vector<vector<int>> combinationSum3(int k, int n) {
backtracking(k,n,1);
return res;
}
};
剪枝优化:
1.目标数n一直在随i的加入减小,如果目标数n已经<0,那么剪枝。即path中的数已经大于目标数了。
2.对for循环i的遍历范围进行缩小
class Solution {
public:
vector<int>path;
vector<vector<int>>res;
//确定递归函数参数和返回值
void backtracking(int k,int n,int startIndex){
//优化:剪枝
if(n<0) return;
//确定终止条件
if(path.size()==k){
if(n==0){
res.push_back(path);
return;
}
}
//确定单层递归逻辑
for(int i=startIndex;i<=10-(k-path.size());i++){//剪枝 优化
n-=i;
path.push_back(i);
backtracking(k,n,i+1);
path.pop_back();
n+=i;
}
}
vector<vector<int>> combinationSum3(int k, int n) {
backtracking(k,n,1);
return res;
}
};
class Solution {
public:
const string letterMap[10]={
"",
"",
"abc",
"def",
"ghi",
"jkl",
"mno",
"pqrs",
"tuv",
"wxyz",
};
vector<string> res;
string s;
//确定递归函数参数和返回值
void backtracing(const string& digits,int index){
//确定终止条件
if(index==digits.size()){
res.push_back(s);
return;
}
//确定单层递归逻辑
int num=digits[index]-'0';
//string str=letterMap[num];
string strr=letterMap[num];
for(int i=0;i<strr.size();i++){
s.push_back(strr[i]);
backtracing(digits,index+1);
s.pop_back();
}
}
vector<string> letterCombinations(string digits) {
if(digits.size()==0){
return res;
}
backtracing(digits,0);
return res;
}
};
class Solution {
public:
vector<int> path;
vector<vector<int>>res;
//确定递归函数参数和返回值
void backtracking(vector<int>& candidates,int target,int startIndex){
//确定终止条件
if(target<0) return;
if(target==0) {
res.push_back(path);
return;
}
//确定单层递归逻辑
for(int i=startIndex;i<candidates.size();i++){
target-=candidates[i];
path.push_back(candidates[i]);
backtracking(candidates,target,i);
target+=candidates[i];
path.pop_back();
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
backtracking(candidates,target,0);
return res;
}
};
优化:(剪枝)
优化后的比之前的在叶子结点少递归一层。在排序candidates后,碰到target<0的情况直接结束本层的遍历,后面没遍历到的也不用遍历了。
class Solution {
public:
vector<int> path;
vector<vector<int>>res;
//确定递归函数参数和返回值
void backtracking(vector<int>& candidates,int target,int startIndex){
//确定终止条件
if(target==0) {
res.push_back(path);
return;
}
//确定单层递归逻辑
for(int i=startIndex;i<candidates.size()&&target-candidates[i]>=0;i++){
target-=candidates[i];
path.push_back(candidates[i]);
backtracking(candidates,target,i);
target+=candidates[i];
path.pop_back();
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
sort(candidates.begin(),candidates.end());
backtracking(candidates,target,0);
return res;
}
};
class Solution {
public:
vector<int>path;
vector<vector<int>>res;
//确定递归函数参数和返回值
void backtracking(vector<int>& candidates,int target,vector<bool>st,int startIndex){
//确定终止条件
if(target<0)return;
if(target==0){
res.push_back(path);
return;
}
//确定单层递归逻辑
for(int i=startIndex;i<candidates.size();i++){
if(i>0&&candidates[i]==candidates[i-1]&&st[i-1]==false){
continue;
}//对组合去重
path.push_back(candidates[i]);
st[i]=true;
target-=candidates[i];
backtracking(candidates,target,st,i+1);
path.pop_back();
st[i]=false;
target+=candidates[i];
}
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
vector<bool>st(candidates.size(),false);
sort(candidates.begin(),candidates.end());
backtracking(candidates,target,st,0);
return res;
}
};
class Solution {
public:
//确定是否是回文
bool isTrue(string s,int start,int end){
for(int i=start,j=end;i<j;){
if(s[i]!=s[j]){
return false;
}
else {
i++;
j--;
}
}
return true;
}
//确定递归函数参数和返回值
void backtracking(vector<string>& path,vector<vector<string>>& res,int startIndex,string s){
//确定终止条件
if(startIndex==s.size()){
res.push_back(path);
return;
}
//确定单层递归逻辑
for(int i=startIndex;i<s.size();i++){
if(isTrue(s,startIndex,i)){
string str=s.substr(startIndex,i-startIndex+1);
path.push_back(str);
}
else{
continue;
}
backtracking(path,res,i+1,s);
path.pop_back();
}
}
vector<vector<string>> partition(string s) {
vector<string>path;
vector<vector<string>>res;
backtracking(path,res,0,s);
return res;
}
};
class Solution {
public:
//确判断是否符合ip地址
bool isTrue(string s,int start,int end){
if(start>end) return false;
if(s[start]=='0'&&start!=end) return false;
int num=0;
for(int i=start;i<=end;i++){
if(s[i]<'0'||s[i]>'9') return false;
num=num*10+(s[i]-'0');
if(num>255)return false;
}
return true;
}
//确定递归函数参数和返回值
void backtracking(string &s,int startIndex,int pointNum,vector<string>&res){
//确定终止条件
if(pointNum==3){
if(isTrue(s,startIndex,s.size()-1)){
res.push_back(s);
}
return;
}
//确定单层递归逻辑
for(int i=startIndex;i<s.size();i++){
if(isTrue(s,startIndex,i)){
s.insert(s.begin()+i+1,'.');
pointNum+=1;
backtracking(s,i+2,pointNum,res);
pointNum-=1;
s.erase(s.begin()+i+1);
}
else break;
}
}
vector<string> restoreIpAddresses(string s) {
vector<string>res;
if(s.size()<4||s.size()>12) return res;
backtracking(s,0,0,res);
return res;
}
};
class Solution {
public:
vector<int>path;
vector<vector<int>>res;
//确定递归函数参数和返回值
void backtracking(int startIndex,vector<int>nums){
res.push_back(path);//不会漏掉自己,空集
//确定终止条件
if(startIndex>=nums.size()) return;
//确定单层递归逻辑
for(int i=startIndex;i<nums.size();i++){
path.push_back(nums[i]);
backtracking(i+1,nums);
path.pop_back();
}
}
vector<vector<int>> subsets(vector<int>& nums) {
backtracking(0,nums);
return res;
}
};
class Solution {
public:
vector<int>path;
vector<vector<int>>res;
//确定递归函数参数和返回值
void backtracking(vector<int>nums,int startIndex,vector<bool>&st){
res.push_back(path);
//确定终止条件
if(startIndex>=nums.size())return;
//确定单层递归逻辑
for(int i=startIndex;i<nums.size();i++){
if(i>0&&nums[i]==nums[i-1]&&st[i-1]==false){
continue;
}
path.push_back(nums[i]);
st[i]=true;
backtracking(nums,i+1,st);
path.pop_back();
st[i]=false;
}
}
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
vector<bool> st(nums.size(),false);
sort(nums.begin(),nums.end());
backtracking(nums,0,st);
return res;
}
};
也可以不用st数组去重
class Solution {
public:
vector<int>path;
vector<vector<int>>res;
//确定递归函数参数和返回值
void backtracking(vector<int>nums,int startIndex){
res.push_back(path);
//确定终止条件
if(startIndex>=nums.size())return;
//确定单层递归逻辑
for(int i=startIndex;i<nums.size();i++){
if(i>startIndex&&nums[i]==nums[i-1]){
continue;
}
path.push_back(nums[i]);
backtracking(nums,i+1);
path.pop_back();
}
}
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
sort(nums.begin(),nums.end());
backtracking(nums,0);
return res;
}
};
class Solution {
public:
vector<int>path;
vector<vector<int>>res;
//确定递归函数参数和返回值
void backtracking(vector<int>& nums,int startIndex){
if(path.size()>1){
res.push_back(path);
}
//确定终止条件
if(startIndex>=nums.size()){
return;
}
//确定单层递归逻辑
unordered_set<int> uset;//对每层去重
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();
}
}
vector<vector<int>> findSubsequences(vector<int>& nums) {
backtracking(nums,0);
return res;
}
};
利用数组去重,因为题目的数值范围小,所以可以尽量使用。
class Solution {
public:
vector<int>path;
vector<vector<int>>res;
//确定递归函数参数和返回值
void backtracking(vector<int>& nums,int startIndex){
if(path.size()>1){
res.push_back(path);
}
//确定终止条件
if(startIndex>=nums.size()){
return;
}
//确定单层递归逻辑
int st[201]={0};//对每层去重
for(int i=startIndex;i<nums.size();i++){
if((!path.empty()&&nums[i]<path.back())||st[nums[i]+100]==1){
continue;
}
st[nums[i]+100]=1;;//记录该元素在本层用过了,之后的相同元素不再使用
path.push_back(nums[i]);
backtracking(nums,i+1);
path.pop_back();
}
}
vector<vector<int>> findSubsequences(vector<int>& nums) {
backtracking(nums,0);
return res;
}
};
class Solution {
public:
vector<int>path;
vector<vector<int>>res;
//确定递归函数参数和返回值
void backtracking(vector<int>& nums,vector<bool>& st){
//确定终止条件
if(path.size()==nums.size()){
res.push_back(path);
return;
}
//确定单层递归逻辑
for(int i=0;i<nums.size();i++){
if(st[i]==true) continue;
st[i]=true;
path.push_back(nums[i]);
backtracking(nums,st);
path.pop_back();
st[i]=false;
}
}
vector<vector<int>> permute(vector<int>& nums) {
vector<bool> st(nums.size(),false);
backtracking(nums,st);
return res;
}
};
class Solution {
public:
vector<int>path;
vector<vector<int>>res;
//确定递归函数参数和返回值
void backtracking(vector<int>& nums,vector<bool>& st){
//确定终止条件
if(path.size()==nums.size()){
res.push_back(path);
return;
}
//确定单层递归逻辑
for(int i=0;i<nums.size();i++){
if(i>0&&nums[i]==nums[i-1]&&st[i-1]==false){
continue;//树层去重的
}
if(st[i]==true) continue;//树枝去重
st[i]=true;
path.push_back(nums[i]);
backtracking(nums,st);
path.pop_back();
st[i]=false;
}
}
vector<vector<int>> permuteUnique(vector<int>& nums) {
vector<bool>st(nums.size(),false);
sort(nums.begin(),nums.end());
backtracking(nums,st);
return res;
}
};
class Solution {
public:
//unordered_map<出发机场,map<到达机场,航班次数>>targets;
unordered_map<string,map<string,int>>targets;
//确定递归函数参数和返回值
bool backtracking(int ticketNum,vector<string>& res){
//确定终止条件
if(res.size()==ticketNum+1){
return true;
}
//确定单层递归逻辑
for(pair<const string, int>&target:targets[res[res.size()-1]]){
if(target.second>0){//记录到达机场是否飞过了
res.push_back(target.first);
target.second--;
if(backtracking(ticketNum,res)) return true;
res.pop_back();
target.second++;
}
}
return false;
}
vector<string> findItinerary(vector<vector<string>>& tickets) {
vector<string>res;
for(const vector<string>& vec:tickets){
targets[vec[0]][vec[1]]++;//记录映射关系
}
res.push_back("JFK");
backtracking(tickets.size(),res);
return res;
}
};
class Solution {
public:
vector<vector<string>>res;
//判断位置是否合法
bool isValid(int n,int col,int row,vector<string>& chessBorad){
//同一列
for(int i=row-1;i>=0;i--){
if(chessBorad[i][col]=='Q')return false;
}
//东北夹角
for(int i=row-1,j=col+1;i>=0&&j<n;i--,j++){
if(chessBorad[i][j]=='Q') return false;
}
//西北夹角
for(int i=row-1,j=col-1;i>=0&&j>=0;i--,j--){
if(chessBorad[i][j]=='Q') return false;
}
return true;
}
//确定递归函数参数和返回值
void backtracking(int n,int row,vector<string>& chessBorad){
//确定终止条件
if(n==row){
res.push_back(chessBorad);
return ;
}
//确定单层递归逻辑
for(int col=0;col<n;col++){
if(!isValid(n,col,row,chessBorad)){
continue;
}
else{
chessBorad[row][col]='Q';
backtracking(n,row+1,chessBorad);
chessBorad[row][col]='.';
}
}
}
vector<vector<string>> solveNQueens(int n) {
vector<string> chessBorad(n,string(n,'.'));
backtracking(n,0,chessBorad);
return res;
}
};
class Solution {
public:
bool isValid(int row,int col,char val,vector<vector<char>>& board){
//行判断
for(int i=0;i<9;i++){
if(board[row][i]==val) return false;
}
//列判断
for(int i=0;i<9;i++){
if(board[i][col]==val) return false;
}
//九宫格内判断
row=(row/3)*3;
col=(col/3)*3;
for(int i=row;i<row+3;i++){
for(int j=col;j<col+3;j++){
if(board[i][j]==val) return false;
}
}
return true;
}
bool backtracking(vector<vector<char>>& board){
//不需要单独的终止条件,不需要收集结果
//确定单层递归逻辑
for(int row=0;row<board.size();row++){
for(int col=0;col<board[0].size();col++){
if(board[row][col]=='.'){
for(char val='1';val<='9';val++){
if(isValid(row,col,val,board)){
board[row][col]=val;
if(backtracking(board)) return true;
board[row][col]='.';
}
}
return false;
}
}
}
return true;
}
void solveSudoku(vector<vector<char>>& board) {
backtracking(board);
}
};