17. 电话号码的字母组合

1. 题目

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

img

示例 1:

1
2
输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]

示例 2:

1
2
输入:digits = ""
输出:[]

示例 3:

1
2
输入:digits = "2"
输出:["a","b","c"]

提示:

  • 0 <= digits.length <= 4
  • digits[i] 是范围 ['2', '9'] 的一个数字。

2. 思路

  • 初始化数字按钮哈希表映射,KEY为数字按钮的值,VALUE则为数字按钮对应可能的英文字符数组
  • 当输入的数字为0时,直接返回空数组,本题主要思想采用的是DFS回溯算法
  • 初始化结果字符串数组result,定义dfs函数,入参为:result结果数组,arr字符数组,index下标,str构建的字符串
  • DFS函数中,如果str的长度与输入的字符串长度一致,则说明已得到一个结果,则可直接写入结果数组result
  • 否则根据当前index下标对应的数字字符从数字按钮哈希表映射中获取对应数字的英文字符数组,并遍历该英文字符数组,取出字符后追加到str末尾处,同时重复调用dfs函数,并将index + 1,以便深入拼接各类可能存在的字符串
  • 完成遍历后,将可变字符串str的末尾字符删除,以便进行下一轮字符的遍历,整体效果如下所示:

1573829897(1).jpg

3. 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class Solution {
private static final Map<Character, List<Character>> DIGIT_MAP = Map.of(
'2', List.of('a', 'b', 'c'),
'3', List.of('d', 'e', 'f'),
'4', List.of('g', 'h', 'i'),
'5', List.of('j', 'k', 'l'),
'6', List.of('m', 'n', 'o'),
'7', List.of('p', 'q', 'r', 's'),
'8', List.of('t', 'u', 'v'),
'9', List.of('w', 'x', 'y', 'z')
);

public List<String> letterCombinations(String digits) {
if (digits.length() == 0) {
return List.of();
}

var result = new ArrayList<String>();
var arr = digits.toCharArray();

dfs(result, arr, 0, new StringBuilder());

return result;
}

private void dfs(List<String> result, char[] arr, int index, StringBuilder str) {
if (str.length() == arr.length) {
result.add(str.toString());
return;
}

var letters = DIGIT_MAP.get(arr[index]);
for (var letter : letters) {
str.append(letter);
dfs(result, arr, index + 1, str);
str.deleteCharAt(str.length() - 1);
}
}
}

4. 复杂度

  • 时间复杂度: O(4^n),其中4为每个数字按键对应的最长字符数量,n为对应的按键输入长度
  • 空间复杂度: O(n)

image-20231221222626858