给定一个仅包含数字 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']
的一个数字。
我最开始是使用了一个回溯函数来解题
class Solution {
public:
// 定义电话键盘上的字母映射
const std::string letterMap[10] = {
"", // 0
"", // 1
"abc", // 2
"def", // 3
"ghi", // 4
"jkl", // 5
"mno", // 6
"pqrs", // 7
"tuv", // 8
"wxyz", // 9
};
std::vector<std::string> res;
// 函数:生成电话号码的字母组合
std::vector<std::string> letterCombinations(const std::string& digits) {
if (!digits.empty()) {
backtrack(digits, 0, "");
}
return res;
}
private:
// 回溯函数
void backtrack(const std::string& digits, int index, std::string path) {
// 如果当前路径长度等于输入数字长度,表示找到一个有效组合
if (index == digits.size()) {
res.push_back(path);
return;
}
// 获取当前数字对应的字母集合
int num = digits[index] - '0';
const std::string& letters = letterMap[num];
// 遍历当前数字对应的每个字母
for (char letter : letters) {
path.push_back(letter); // 将字母添加到当前路径
backtrack(digits, index + 1, path); // 递归处理下一个数字
path.pop_back(); // 回溯,移除当前字母
}
}
};
运行时间可以达到最短,但是所需要的内存很大。
在学习了他人的思路后我使用了下面的算法,是一个经典的递归(深度优先搜索,DFS)实现,用于生成电话号码的字母组合。每个数字按电话键盘的映射对应多个字母,代码通过递归逐步构建每个可能的组合。
class Solution {
public:
// 主函数,负责调用 DFS 并返回结果
vector<string> letterCombinations(string digits) {
// 如果输入字符串为空,直接返回空向量
if (digits.empty()) return {};
// 构建一个向量数组,每个元素是一个字符向量,对应电话键盘上的字母
vector<vector<char>> d(10);
d[0] = {' '}; // 0 键对应空格(通常没有字母,这里设置为一个空格)
d[1] = {}; // 1 键没有对应的字母
d[2] = {'a','b','c'}; // 2 键对应 'abc'
d[3] = {'d','e','f'}; // 3 键对应 'def'
d[4] = {'g','h','i'}; // 4 键对应 'ghi'
d[5] = {'j','k','l'}; // 5 键对应 'jkl'
d[6] = {'m','n','o'}; // 6 键对应 'mno'
d[7] = {'p','q','r','s'}; // 7 键对应 'pqrs'
d[8] = {'t','u','v'}; // 8 键对应 'tuv'
d[9] = {'w','x','y','z'}; // 9 键对应 'wxyz'
vector<string> ans; // 存储结果的向量
string cur = ""; // 当前构建的字符串
// 调用递归函数开始 DFS
dfs(digits, d, 0, cur, ans);
return ans; // 返回最终结果
}
private:
// 递归函数,生成所有可能的字母组合
void dfs(const string& digits, const vector<vector<char>>& d, int l, string& cur, vector<string>& ans) {
// 递归终止条件:如果已经处理完所有的数字
if (l == digits.size()) {
ans.push_back(cur); // 将当前构建的字符串添加到结果中
return;
}
// 获取当前数字对应的字母列表
for (char c: d[digits[l] - '0']) {
cur.push_back(c); // 将当前字母添加到当前构建的字符串中
dfs(digits, d, l + 1, cur, ans); // 递归处理下一个数字
cur.pop_back(); // 回溯,移除最后一个添加的字母
}
}
};
运行时间稍长但是需要内存极少