回溯法
回溯法是优先搜索的一种特殊情况,又称为试探法,常用于记录节点状态的深度优先搜索。
其核心是回溯,在搜索到某一节点的时候,如果发现目前节点及子节点并不是需求目标时,回退到原来的节点继续搜索,并且把目前节点修改的状态还原。
一般有两种情况,一种是修改最后一位输出,比如排列组合;一种是修改访问标记,比如矩阵里搜字符串。
**
题目一
给定一个无重复数字的整数数组,求其所有的排列方式
//对于每一个当前位置i,我们可以将其与之后的任意位置交换,然后继续处理位置i+1,直到处理最后一位
//主函数
vector<vector<int>>permute(vector<int>&nums){
vector<vector<int>>ans;
backtracking(nums,0,ans);
return ans;
}
//辅函数
void backtracking(vector<int>&nums,int level,vector<vector<int>>&ans){
if(level==nums.size()-1){
ans.push_back(nums);
return;
}
for(int i=level;i<num.size();i++){
swap(nums[i],nums[level]);//修改当前节点状态
backtracking(nums,level+1,ans);//递归子节点
swap(nums[i],nums[level]);//回改当前节点状态
}
题目二
给定一个整数n和一个整数k,求在1到n中选取k个数字的所有组合方法
//zhu
vector<vector<int>>combine(int n,int k){
vector<vector<int>>ans;
vector<int>comb(k,0);
int count=0;
backtracking(ans,comb,count,1,n,k);
return ans;
}
//fu
void backtracking(vector<vector<int>>&ans,vector,int&count,int pos,int n,int k){
if(count==k){
ans.push_back(comb);
return;
}
for(int i=pos;i<=n,++i){
comb[count++]=i;//修改当前节点状态
backtracking(ans,comb,count,i+1,n,k);//递归子节点
--count;//回改当前节点状态
}
}
题目三
给定一个字母矩阵,所有的字母都与上下左右四个方向上的字母相连。给定一个字符串,求
字符串能不能在字母矩阵中寻找到。
//主函数
bool exist(vector<vector<char>>&board,string word){
if(board.empty()) return false;
int m=board.size(),n=board[0].size();
vector<vector<bool>>visited(m,vector<bool>(n,false));
bool find=false;
for(int i=0;i<m;++i){
for(int j=0;j<n;++j){
backtracking(i,j,board,word,find,visited,0);
}
}
return find;
}
//fuhanshu
void backtracking(int i,int j,vector<vector<char>>&board,string&word,bool&find,
vector<vector<bool>>&visited,int pos){
if(i<0||i>=board.size()||j<0||j>=board[0].size()){
return;
}
if(visited[i][j]||find||board[i][j]!=word[pos]){
return;
}
if(pos==word.size()-1){
find==true;
return;
}
visited[i][j]=true;//修改当前节点状态
//递归子节点
backtracking(i+1,j,board,word,find,visited,pos+1);
backtracking(i-1,j,board,word,find,visited,pos+1);
backtracking(i,j+1,board,word,find,visited,pos+1);
backtracking(i,j-1,board,word,find,visited,pos+1);
visited[[i][j]=false;//回改当前节点状态
}
题目四
给定一个大小为 n 的正方形国际象棋棋盘,求有多少种方式可以放置 n 个皇后并使得她们互
不攻击,即每一行、列、左斜、右斜最多只有一个皇后。例图如下:
//主函数
vector<vector<string>>solveNQueens(int n){
vector<vector<string>>ans;
if(n==0){
return ans;
}
vector<string>board(n,string(n,','));
vector<bool>column(n,false),ldiag(2*n-1,false),rdiag(2*n-1,false);
backtranking(ans,board,column,ldiag,rdiag,0,n);
return ans;
}
//fuhanshu
void backreacking(vector<vector<string>>&ans,vector<string>&board,vector<bool>&column,
vector<bool>&ldiag,vector<bool>&rdiag,int row,int n){
if(row==n){
ans.push_back(board);
return;
}
for(int i=0;i<n;++i){
if(column[i]||ldiag[n-row+i-1]||rdiag[row+i+1]){
continue;
}
//修改当前节点状态
board[row][i]='Q';
column[i]=ldiag[n-row+i-1]=rdiag[row+i+1]=true;
//递归子节点
backtracking(ans,board,column,ldiag,rdiag,row+1,n);
//回改当前节点装填
board[row][i]='.';
column[i]=ldiag[n-row+i-1]=rdiag[row+i+1]=false;
}
}