这是我参与11月更文挑战的第25天,活动详情查看:2021最后一次更文挑战
电话号码的字母组合
Hot100 17. 电话号码的字母组合
难度:中等
给定一个仅包含2-9的字符串,返回所有它能表示的字母组合。答案可以按任意顺序返回。给出数字到字母的映射如下(与电话按键相同)。注意1不对应任何字母。
示例1:
输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]
示例2:
输入:digits = ""
输出:[]
示例3:
输入:digits = "2"
输出:["a","b","c"]
提示:
0 <= digits.length <= 4digits[i]是范围['2', '9']的一个数字。
题解
刚开始可能发现使用暴力法来解,比如"23"时可以用两层for循环,但如果是"213",则需要三层for循环,可见,暴力法的方式不可取。
回溯法
回溯法可以用于解决n个for循环的问题。
思路:
- 数字和字母映射,通过一个数组来将下标和字母映射起来。
- 边界条件判定,当digits为空时,返回
[],当digits长度为1时,返回其电话按键的字母。 - 通过画图,我们可以很容易画出一棵多叉树,其叶子结点就是一对字母,利用数组path将其存储,而利用数组res存储path(需数组转字符串)。
- 在递归过程中,若已经递归到底部,则停止递归,并将结果输出。
/**
* @param {string} digits
* @return {string[]}
*/
var letterCombinations = function(digits) {
const depth = digits.length;
const map = ['','','abc','def','ghi','jkl','mno','pqrs','tuv','wxyz'];
if(!depth) return [];
if(depth === 1) return map[digits].split('');
const res = [], path = [];
backtracking(digits, depth, 0);
return res;
// a用于控制digits的进位
function backtracking(digits, depth, a) {
// 当递归到最底层时,将每个递归结果存入res中
if(path.length === depth){
res.push(path.join('')); // 数组转字符串,如['a','b'] => 'ab'
return;
}
for(const v of map[digits[a]]){
path.push(v);
backtracking(digits, depth, a+1);
path.pop();
}
}
};
时间复杂度:O(3^m×4^n),其中 m 是输入中对应 3 个字母的数字个数(包括数字 2、3、4、5、6、8),n是输入中对应 4个字母的数字个数(包括数字 7、9)。
空间复杂度:O(m+n),m+n是输入数字的总个数。
坚持每日一练!前端小萌新一枚,希望能点个赞+在看哇~