📝 题目描述

题目链接电话号码的字母组合

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

示例:

1
2
3
4
5
6
7
8
9
示例 1:

输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]

示例 2:

输入:digits = "2"
输出:["a","b","c"]

提示:

  • 1 <= digits.length <= 4
  • digits[i] 是范围 ['2', '9'] 的一个数字

💡 解题思路

方法一:回溯

按照经典的回溯模板撰写即可。

首先使用一个二维数组存储每个数字对应的字母。

然后在回溯过程中,维护一个字符串,表示已有的字母排列(如果未遍历完电话号码的所有数字,则已有的字母排列是不完整的)。该字符串初始为空。每次取电话号码的一位数字,从哈希表中获得该数字对应的所有可能的字母,并将其中的一个字母插入到已有的字母排列后面,然后继续处理电话号码的后一位数字,直到处理完电话号码中的所有数字,即得到一个完整的字母排列。然后进行回退操作,遍历其余的字母排列。

🔧 代码实现

1、回溯

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution {
public:
vector<string> ans;
vector<vector<char>> letters;
void backtrack(string& digits, int current, string& track) {
if (current == digits.size()) {
ans.push_back(track);
return;
}
for (int i = 0; i < letters[digits[current] - '2'].size(); i++) {
track.push_back(letters[digits[current] - '2'][i]);
backtrack(digits, current + 1, track);
track.pop_back();
}
}
vector<string> letterCombinations(string digits) {
letters = {{'a', 'b', 'c'}, {'d', 'e', 'f'}, {'g', 'h', 'i'}, {'j', 'k', 'l'}, {'m', 'n', 'o'}, {'p', 'q', 'r', 's'}, {'t', 'u', 'v'}, {'w', 'x', 'y', 'z'}};
string track;
backtrack(digits, 0, track);
return ans;
}
};

📊 复杂度分析

1、回溯

  • 时间复杂度O(3m×4n)O(3^m×4^n),其中 m 是输入中对应 3 个字母的数字个数(包括数字 2、3、4、5、6、8),n 是输入中对应 4 个字母的数字个数(包括数字 7、9),m+n 是输入数字的总个数。当输入包含 m 个对应 3 个字母的数字和 n 个对应 4 个字母的数字时,不同的字母组合一共有 3m×4n3^m×4^n 种,需要遍历每一种字母组合。
  • 空间复杂度O(m+n)O(m+n),其中 m 是输入中对应 3 个字母的数字个数,n 是输入中对应 4 个字母的数字个数,m+n 是输入数字的总个数。除了返回值以外,空间复杂度主要取决于哈希表以及回溯过程中的递归调用层数,哈希表的大小与输入无关,可以看成常数,递归调用层数最大为 m+n。

🎯 总结

  • 核心思想:掌握回溯的模板写法。