Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
前言
今天第二题难度为中等,主要是涉及到了递归的问题,我是使用了回溯算法来进行解题,当然这不是唯一解,dfs的解法应该也是能够求出这道题的答案的
每日一题
第二题的题目是 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 <= 4
- digits[i] 是范围 ['2', '9'] 的一个数字。
题解
回溯算法
关于回溯算法,解决的问题也很直观,我们看一下题目,要求用每个数字代表的字母组成所有情况,比如说两个数字 “23” 那么就是:
let num2 = 'abc'
let num3 = 'def'
let res = []
for(let i=0;i<num2.length;i++){
for(let j=0;j<num3.length;j++){
res.push(num2[i] + num3[j])
}
}
return res
最后获得的这个 res 就是我们要的数组了,但是,如果当题目给出的 digits 更长呢,那么这个循环将会嵌套特比多层,那么就特别头疼了,所以这时候我们就需要用回溯算法来解决这个问题。
现在我们需要设计一个递归函数,然后我们来思考这个函数的退出条件,看到题目给的 digits 和之后的答案数组,我们不难发现,答案数组中的每一个元素,长度都是和 digits 相同的,那么我们就能够知道了,在什么时候我们会成功组合出一个答案呢,当这个答案的长度等于 digits 的时候。
那么在得出了退出条件之后,我们就需要在每一次递归的时候去加长我们的其中一个答案元素,那么这个答案元素从哪里来,很明显,我们可以用一个数组存下题目给的 2-9 这 8 个数字相对于的字符串,然后每次加长的长度就是从这些字符串里来。
那么将以上结合起来,我们需要一个临时数组,用于存放每一个答案元素,在满足退出条件的时候,也就是长度等于 digits 的时候将它加入答案数组,并且退出递归。
/**
* @param {string} digits
* @return {string[]}
*/
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("");
let res = [];
let path = [];
function recursion(a) {
if (path.length === k) {
res.push(path.join(""));
return;
}
for (const v of map[digits[a]]) {
path.push(v);
recursion(a + 1);
path.pop();
}
}
recursion(0);
return res;
};