57.电话号码的字母组合(学习)
给定一个仅包含数字 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’] 的一个数字。
解析:
一、定义映射表:
1.首先,我们定义了一个名为digitMap的对象,它包含了从数字到对应字母列表的映射。这是基于电话按键的映射关系。
二、初始化结果数组:
1.我们创建了一个名为result的空数组,用于存储所有生成的字母组合。
三、定义递归函数backtrack:
这个函数是解决方案的核心。它接受两个参数:
1.combination:当前已经生成的字母组合(字符串形式)。
2.nextDigits:尚未处理的数字字符串。
函数的工作流程如下:
1.基准情况:如果nextDigits为空,说明我们已经处理了所有的数字,此时将combination添加到result数组中。
2.递归步骤:如果nextDigits不为空,我们执行以下操作:
2.1.取出nextDigits的第一个数字(digit),并查找它在digitMap中对应的字母列表(letters)。
2.2.遍历letters中的每个字母(letter),执行以下操作:
2.2.1将letter添加到combination的末尾,形成新的组合。
2.2.2递归调用backtrack函数,传入新的组合和nextDigits中除了第一个数字之外的部分(通过slice(1)实现)。
2.2.3递归返回后,我们需要撤销上一步的选择,即移除刚刚添加到combination中的letter。但在这个特定的实现中,由于JavaScript的字符串是不可变的,我们实际上是通过创建新的字符串来“撤销”的,因为每次递归调用都会传入一个新的combination字符串。
四、处理边界情况:
1.如果输入的digits字符串为空,我们直接返回空数组,因为没有数字就没有字母组合。
五、启动递归:
1.我们调用backtrack函数,传入空字符串作为初始的combination,以及输入的digits字符串作为nextDigits。
六、返回结果:
1.递归完成后,result数组将包含所有可能的字母组合,我们将其返回作为最终结果。
var letterCombinations = function (digits) {
// 映射表
const digitMap = {
'2': ['a', 'b', 'c'],
'3': ['d', 'e', 'f'],
'4': ['g', 'h', 'i'],
'5': ['j', 'k', 'l'],
'6': ['m', 'n', 'o'],
'7': ['p', 'q', 'r', 's'],
'8': ['t', 'u', 'v'],
'9': ['w', 'x', 'y', 'z']
};
// 结果数组
const result = [];
// 递归函数
const backtrack = (combination, nextDigits) => {
// 如果已经处理了所有数字,则将当前组合添加到结果中
if (nextDigits.length === 0) {
result.push(combination);
} else {
// 获取当前处理的数字对应的字母列表
const digit = nextDigits[0];
const letters = digitMap[digit];
// 遍历字母列表,进行递归
for (let letter of letters) {
backtrack(combination + letter, nextDigits.slice(1));
}
}
};
// 如果输入为空字符串,则直接返回空数组
if (digits.length === 0) {
return result;
}
// 调用递归函数,初始组合为空字符串,初始数字为输入的字符串
backtrack('', digits);
return result;
};