Medium
题目描述
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例 1:
输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]
示例 2:
输入:digits = "2"
输出:["a","b","c"]
提示:
1 <= digits.length <= 4digits[i]是范围['2', '9']的一个数字。
解题思路
解题思路
这是一个经典的回溯(Backtracking)问题。我们需要遍历所有可能的字母组合。
核心思想:
- 建立映射:首先建立数字到字母的映射关系,如数字2对应"abc",数字3对应"def"等
- 回溯搜索:使用深度优先搜索(DFS)的方式,对每个数字位置尝试所有可能的字母
- 状态管理:维护当前已构建的字符串,当长度等于输入数字串长度时,说明找到一个完整组合
算法步骤:
- 特殊情况处理:如果输入为空,直接返回空列表
- 定义数字到字母的映射表
- 使用回溯函数,参数包括当前构建的字符串和当前处理的数字索引
- 对于当前数字,尝试其对应的每个字母,递归处理下一个数字
- 当处理完所有数字时,将当前字符串加入结果集
这种方法的优势是思路清晰,代码简洁,时间复杂度最优。
代码实现
class Solution {
public:
vector<string> letterCombinations(string digits) {
if (digits.empty()) return {};
vector<string> mapping = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
vector<string> result;
string current;
backtrack(digits, 0, current, mapping, result);
return result;
}
private:
void backtrack(const string& digits, int index, string& current,
const vector<string>& mapping, vector<string>& result) {
if (index == digits.length()) {
result.push_back(current);
return;
}
int digit = digits[index] - '0';
for (char c : mapping[digit]) {
current.push_back(c);
backtrack(digits, index + 1, current, mapping, result);
current.pop_back();
}
}
};
class Solution:
def letterCombinations(self, digits: str) -> List[str]:
if not digits:
return []
mapping = {
'2': 'abc', '3': 'def', '4': 'ghi', '5': 'jkl',
'6': 'mno', '7': 'pqrs', '8': 'tuv', '9': 'wxyz'
}
result = []
def backtrack(index, current):
if index == len(digits):
result.append(current)
return
digit = digits[index]
for letter in mapping[digit]:
backtrack(index + 1, current + letter)
backtrack(0, "")
return result
public class Solution {
public IList<string> LetterCombinations(string digits) {
if (string.IsNullOrEmpty(digits)) return new List<string>();
var mapping = new Dictionary<char, string> {
{'2', "abc"}, {'3', "def"}, {'4', "ghi"}, {'5', "jkl"},
{'6', "mno"}, {'7', "pqrs"}, {'8', "tuv"}, {'9', "wxyz"}
};
var result = new List<string>();
void Backtrack(int index, string current) {
if (index == digits.Length) {
result.Add(current);
return;
}
char digit = digits[index];
foreach (char letter in mapping[digit]) {
Backtrack(index + 1, current + letter);
}
}
Backtrack(0, "");
return result;
}
}
var letterCombinations = function(digits) {
if (digits.length === 0) return [];
const map = {
'2': 'abc',
'3': 'def',
'4': 'ghi',
'5': 'jkl',
'6': 'mno',
'7': 'pqrs',
'8': 'tuv',
'9': 'wxyz'
};
const result = [];
function backtrack(index, current) {
if (index === digits.length) {
result.push(current);
return;
}
const letters = map[digits[index]];
for (let letter of letters) {
backtrack(index + 1, current + letter);
}
}
backtrack(0, '');
return result;
};
复杂度分析
| 复杂度类型 | 分析 |
|---|---|
| 时间复杂度 | O(3^m × 4^n),其中 m 是对应 3 个字母的数字个数,n 是对应 4 个字母的数字个数。最坏情况下每个数字对应 4 个字母,总共 4^4 种组合 |
| 空间复杂度 | O(3^m × 4^n),递归调用栈深度为输入字符串长度,结果存储空间与组合总数成正比 |
相关题目
. Generate Parentheses (Medium)
. Combination Sum (Medium)
. Binary Watch (Easy)
. Count Number of Texts (Medium)