回溯算法:
使用深度优先搜索遍历
使用场合:
- 组合问题:N个数里面按一定规则找出k个数的集合
- 排列问题:N个数按一定规则全排列,有几种排列方式
- 切割问题:一个字符串按一定规则有几种切割方式
- 子集问题:一个N个数的集合里有多少符合条件的子集
- 棋盘问题:N皇后,解数独等等
void backtracking(参数) {
if (终止条件) {
存放结果;
return;
}
for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
处理节点;
backtracking(路径,选择列表); // 递归
回溯,撤销处理结果
}
}
17.电话号码的字母组合:
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]
思路:
先获取字符串的长度:len const map = ["","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"];
如果len=0返回空 len=1 直接拆开 return map[digits].split("")
大于1使用回溯算法
/**
* @param {string} digits
* @return {string[]}
*/
var letterCombinations = function(digits) {
const len=digits.length;
if(len==0){
return [];
}
const map = ["","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"];
if(len==1){
return map[digits].split("");
}
const res=[];
const pas=[];
back(digits,len,0);//回溯算法
return res;
function back(n,len,a){
if(pas.length==len){//如果获取长度等于初始长度
res.push(pas.join(""));//将获取的数组加入到最终的数组中
return;
}
for(const v of map[n[a]]){//v是单个的字符
pas.push(v);//加入到pas中
back(n,len,a+1);//递归
pas.pop();//删除最后一个
}
}
};
22.括号生成
输入:n = 3 输出:["((()))","(()())","(())()","()(())","()()()"]
var generateParenthesis = function(n) {
if (n == 0) return []
const res = []
let track = []
backtrack(n, n, track, res)
return res
function backtrack(left, right, track, res) {
// 数量小于0,不合法
if (left < 0 || right < 0) return
// 若左括号剩下的多,说明不合法
if (right < left) return
// 所有括号用完,得到合法组合
if (left == 0 && right == 0) {
res.push(track.join(''))
return
}
// 尝试添加左括号
track.push('(')
//这个地方一定要注意 需要拷贝一份track,也就是采用[...track], 不然会影响其他分支
backtrack(left - 1, right, [...track], res)
track.pop()
// 尝试添加右括号
track.push(')')
backtrack(left, right - 1, [...track], res)
track.pop()
}
};