题目链接
题目描述
给定一个仅包含数字 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']
的一个数字。
解题思路
一个数字对应这三个字母,那么答案就是从给定数字对应的字母里面挑选组合。那么将组合问题抽象成树形结构,每次从集合中选取元素,可选择的范围随着选择的进行而收缩,调整可选择的范围。图中可以发现n相当于树的宽度,k相当于树的深度。图中每次搜索到了叶子节点,我们就找到了一个结果
回溯法三部曲
- 递归函数的参数和返回值
digits
:题目给的numString
:数字对应映射的字母num
:用来记录遍历到第几个数字path
:用来存放符合条件的结果ans
:用来存放符合条件的结果的集合
- 回溯函数终止条件
- 到达叶子节点,也就是
path
这个数组的大小达到k
,说明已经找到了一个子集大小为k
的组合了,在图中path
存的就是根节点到叶子节点的路径了 - 此时用
ans
数组将结果保存起来,并终止本层递归
- 到达叶子节点,也就是
- 单层逻辑
- 用
for
循环进行横向遍历,具体来说就是每次从startIndex
开始遍历,然后用path
保存取到的节点i
- 用
AC代码
class Solution {
public List<String> letterCombinations(String digits) {
List<String> ans = new ArrayList<>();
StringBuilder path = new StringBuilder();
if (digits == null || digits.length() == 0) {
return ans;
}
String[] numString = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
backTracing(digits, numString, 0, path, ans);
return ans;
}
private static void backTracing(String digits, String[] numString, int num, StringBuilder path, List<String> ans) {
//终止条件
if (num == digits.length()) {
ans.add(path.toString());
return;
}
String str = numString[digits.charAt(num) - '0'];
for (int i = 0; i < str.length(); i++) {
path.append(str.charAt(i));
backTracing(digits, numString, num + 1, path, ans);
path.deleteCharAt(path.length() - 1);
}
}
}