记录算法学习,输出更有利于学习!
17. 电话号码的字母组合
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
例子 : 输入:digits = "23" 输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]
题目难点:
- 返回组合集中的字符串,要与输入字符串长度一致。由此需要对应长度的 for循环层数。
- 数字和字母之间的对应关系
- 电话号码中 1,#, * 等特殊摁建处理
数字和字母之间的对应关系
可以模拟一个 数组进行对应的映射关系。
const map = ["","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"]
对应长度的 for 循环使用 回溯法(递归)
如图:
回溯三个步骤:
- 确定传入的参数。主要是否需要传入 Index ,可以用于枝剪 、去重直接的操作(这道题没用于去重和枝剪等操作)。 主要需要的参数有 : 输入字母的长度 digits.length ,多长就递归多少层,也用于判断是否需要终止递归。 digits。映射对应的字母 index 记录当前是第几个字母
function backtracking(digits, digits.length, index) {}
- 终止条件。 定义数组去收集结果, 当添加到数组中的字符长度 到达 digits.length 的时候说明已经到达最后一层,需要return
if(path.length === digits.length) {
res.push(path.join(""));
return;
}
- 单层遍历逻辑。 寻找到输入数字中对应的 字符字符串。然后对这个字符串进行递归循环。
for(const v of map[digits[index]]) {
path.push(v);
backtracking(digits, digits.length, index + 1);
path.pop();
}
完整代码
var letterCombinations = function(digits) {
const k = digits.length; // 递归的深度 以及 终止条件
const map = ["","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"]; // 映射的数组
// 特殊情况
if(!k) return [];
if(k === 1) return map[digits].split("");
// 定义一个结果集,一个路径集合
const res = [], path = [];
backtracking(digits, k, 0);
return res;
function backtracking(n, k, a) {
if(path.length === k) {
// 当路径集合 和深度一样,说明已经可以组合完成,可以收集
res.push(path.join(""));
return;
}
for(const v of map[n[a]]) {
path.push(v); // 记录循环的字母
backtracking(n, k, a + 1);
// 回溯,删除当前组合过的数字 如 [a, d] --- [a] 进行下一次循环继续组合
path.pop();
}
}
};