题目描述
给定一个仅包含数字 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']
的一个数字。
解法
思路:回溯算法:循环 + 递归
使用 排序 + 双指针
对于打印"2345"这样的字符串:
第一次递归处理2,将输入的字符改变成"345"并调用第二个递归函数
第二次递归处理3,将字符串改变成"45"后再次递归
第三次递归处理4,将字符串改变成"5"后继续递归
第四次递归处理5,将字符串改变成""后继续递归
最后发现字符串为空了,将结果放到列表中并返回
而每次调用下一层递归时,都需要将本层的一些处理结果放到一个临时变量中,再传递给下一层
java代码:
class Solution {
Map<Character, String> phoneMap = new HashMap<Character, String>() {{
put('2', "abc");
put('3', "def");
put('4', "ghi");
put('5', "jkl");
put('6', "mno");
put('7', "pqrs");
put('8', "tuv");
put('9', "wxyz");
}};
public List<String> letterCombinations(String digits) {
List<String> res = new ArrayList<>();
if (digits.length() == 0) {
return res;
}
// 使用回溯方法
backtrack(res, digits, 0, new StringBuffer());
return res;
}
/**
* 回溯方法
*
* @param res 结果字符串列表
* @param digits 数字字符串,入参
* @param index 索引
* @param combination 缓冲字符串
*/
private void backtrack(List<String> res, String digits, int index, StringBuffer combination) {
// 递归结束条件,索引长度等于字符串长度了,说明参数里的所有数字遍历完了
if (index == digits.length()) {
res.add(combination.toString());
} else {
// 当前索引位置的数字
char digit = digits.charAt(index);
// 拿到数字对应的字母字符串
String letters = phoneMap.get(digit);
// 遍历字符串
for (int i = 0; i < letters.length(); i++) {
// 拿到字符串中的字母
combination.append(letters.charAt(i));
// 继续拿下一个数字对应的字母
backtrack(res, digits, index + 1, combination);
// 把最后一个删除了,再找下一个加进去
combination.deleteCharAt(index);
}
}
}
}
复杂度
时间复杂度:O(3^m * 4^n)
,其中 m 是输入中对应 3 个字母的数字个数(包括数字 2、3、4、5、6、8),n 是输入中对应 4 个字母的数字个数(包括数字 7、9),m+n 是输入数字的总个数。
空间复杂度:O(m + n)