Backtracking(回溯)属于 DFS。
普通 DFS 主要用在 可达性问题 ,这种问题只需要执行到特点的位置然后返回即可。
而 Backtracking 主要用于求解 排列组合 问题,例如有 { ‘a’,‘b’,‘c’ } 三个字符,求解所有由这三个字符排列得到的字符串,这种问题在执行到特定的位置返回之后还会继续执行求解过程。
因为 Backtracking 不是立即返回,而要继续求解,因此在程序实现时,需要注意对元素的标记问题:
在访问一个新元素进入新的递归调用时,需要将新元素标记为已经访问,这样才能在继续递归调用时不用重复访问该元素;
但是在递归返回时,需要将元素标记为未访问,因为只需要保证在一个递归链中不同时访问一个元素,可以访问已经访问过但是不在当前递归链中的元素。
1、电话号码的字母组合
class Solution {
public:
vector<string> table = {
"abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
vector<string> res;
string str;
vector<string> letterCombinations(string digits) {
if(digits.size()==0) return res;
dfs(digits,0);
return res;
}
void dfs(string digits,int index){
if(index==digits.size()){
res.push_back(str);
return;
}
string s = table[digits[index] - '2'];
for(int i=0;i<s.size();i++){
str.push_back(s[i]);
dfs(digits,index+1);
str.pop_back();
}
return;
}
};
2、复原IP地址
class Solution {
public:
bool isValid(string ip)
{
int val = stoi(ip);
if (val > 255) return false;
if (ip.size() >= 2 && ip[0] == '0') return false;
return true;
}
void dfs(string& s, int pos, vector<string> &path, vector<string>& res)
{
//首先判断剩余的位数,是不是还能满足要求,比如25525511135,若2.5.5.25511135显然不满足,这可以预判
//4组,每组最多3位数字
int maxLen = (4 - path.size()) * 3;
if (s.size() - pos > maxLen) return;
if (path.size() == 4 && pos == s.size()) {
string ans = "";
for (int i = 0; i < 4; ++i) {
ans += path[i];
if (i != 3) ans += ".";
}
res.push_back(ans);
return;
}
//回溯算法的典型模式,循环递归
for (int i = pos; i < s.size() && i <= pos + 2; ++i) {
string ip = s.substr(pos, i - pos+1);
if (!isValid(ip)) continue;
path.push_back(ip);
dfs(s, i + 1, path, res);
path.pop_back();
}
}
vector<string> restoreIpAddresses(string s)
{
//找3个.的位置,每个.之前组成的的数值必须要小于255,且以0开头的除非数字是0本身,否则也是非法
vector<string> res;
if (s.size() == 0 || s.size() < 4) return res;
vector<string> path;//存储从根开始的到叶子节点的满足条件的路径,因为最多3位数字一组,所以同一层横向循环时尝试最多3个位的长度
dfs(s, 0, path, res);
return res;
}
};
3、单词搜索
class Solution {
public:
bool exist(vector<vector<char>>& board, string word) {
m=board.size();
n=board[0].size();
if(m==0 || n==0) return false;
vector<vector<bool>> visit(m,vector<bool>(n,false));
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(board[i][j]==word[0]){
if(dfs(board,visit,word,0,i,j))
return true;
}
}
}
return false;
}
private:
int m,n;
int dit[4][2] = {
1,0,-1,0,0,1,0,-1};
bool dfs(vector<vector<char>>& board, vector<vector<bool>>& visit,string& word,int index,int i,int j){
if(i<0 || j<0 || i>=m || j>=n