题目
来源:LeetCode.
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例 1:
输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]
示例 2:
输入:digits = ""
输出:[]
示例 3:
输入:digits = "2"
输出:["a","b","c"]
提示:
- 0 < = d i g i t s . l e n g t h < = 4 0 <= digits.length <= 4 0<=digits.length<=4
- d i g i t s [ i ] 是 范 围 [ ′ 2 ′ , ′ 9 ′ ] 的 一 个 数 字 digits[i] 是范围 ['2', '9'] 的一个数字 digits[i]是范围[′2′,′9′]的一个数字。
接下来看一下解题思路:
思路:回溯:
这个题需要枚举数字所对应的字母的所有组合,所以可以使用回溯来解决;
回溯:把问题的解空间转化成图或者树的结构表示,然后使用深度优先搜索进行遍历,遍历过程中记录和寻找所有可行解或者最优解;
以输入数字是
“
23
”
“23”
“23”为例,我们可以将它转化下面这样的一棵树:
首先使用哈希表存储每个数字对应的所有可能的字母,然后进行回溯操作;
回溯过程中维护一个字符串,表示已有的字母排列
该字符串初始为空。每次取电话号码的一位数字,从哈希表中获得该数字对应的所有可能的字母,并将其中的一个字母插入到已有的字母排列后面,然后继续处理电话号码的后一位数字,直到处理完电话号码中的所有数字,即得到一个完整的字母排列;
然后进行回退操作,遍历其余的字母排列;
回溯算法用于寻找所有的可行解,如果发现一个解不可行,则会舍弃不可行的解;
在这道题中,由于每个数字对应的每个字母都可能进入字母组合,因此不存在不可行的解,直接穷举所有的解即可;
public static List<String> letterCombinations(String digits) {
List<String> result = new ArrayList<>();
Map<Character, String> map = new HashMap<>();
if (digits == "" || digits == null) {
return result;
}
map.put('2', "abc");
map.put('3', "def");
map.put('4', "ghi");
map.put('5', "jkl");
map.put('6', "mno");
map.put('7', "pqrs");
map.put('8', "tuv");
map.put('9', "wxyz");
backtrack(result, map, digits, 0, new StringBuffer());
return result;
}
// 回溯
private static void backtrack(List<String> result, Map<Character, String> map, String digits, int index, StringBuffer combination) {
if (index == digits.length()) {
result.add(combination.toString());
} else {
char digit = digits.charAt(index);
String letters = map.get(digit);
int letterCount = letters.length();
for (int i = 0; i < letterCount; ++i) {
combination.append(letters.charAt(i));
backtrack(result, map, digits, index + 1, combination);
combination.deleteCharAt(index);
}
}
}
我们用index
表示当前遍历的层数;
回溯的过程中,用result
来保存最终的结果,当访问的index
出界时,将combination
放入到result
里;combination
是一个动态字符串,可以理解为堆栈,层数增加时是入栈,返回上一层是出栈;
总结
时间复杂度:
O
(
3
m
×
4
n
)
O(3^m \times 4^n)
O(3m×4n),其中
m
m
m 是输入中对应
3
3
3个字母的数字个数(包括数字 22、33、44、55、66、88),
n
n
n 是输入中对应
4
4
4 个字母的数字个数(包括数字 77、99),
m
+
n
m+n
m+n 是输入数字的总个数。当输入包含
m
m
m 个对应
3
3
3 个字母的数字和
n
n
n 个对应
4
4
4 个字母的数字时,不同的字母组合一共有
3
m
×
4
n
3^m \times 4^n
3m×4n 种,需要遍历每一种字母组合;
空间复杂度:
O
(
m
+
n
)
O(m+n)
O(m+n),其中
m
m
m 是输入中对应
3
3
3 个字母的数字个数,
n
n
n 是输入中对应
4
4
4 个字母的数字个数,
m
+
n
m+n
m+n 是输入数字的总个数。除了返回值以外,空间复杂度主要取决于哈希表以及回溯过程中的递归调用层数,哈希表的大小与输入无关,可以看成常数,递归调用层数最大为
m
+
n
m+n
m+n;