题目:
给定一个仅包含数字
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']
的一个数字。
1. 思路
这道题可以使用回溯法来解决。回溯法是一种通过探索所有可能的候选解来找出所有的解的算法。在搜索过程中,当发现已经不满足求解条件的路径时,就会回溯到上一个节点,继续探索其他的路径。在这个问题中,我们可以通过递归来实现回溯法,每次递归中选择一个数字对应的所有可能字母进行组合。
2. 解题方法
- 定义一个哈希表,存储数字与字母的映射关系。
- 定义一个列表
combinations
,用于存储所有可能的字母组合。 - 编写递归函数
backtrack
,接收两个参数:当前数字串currentDigits
和当前已组合的字符串combination
。 - 在递归函数中,首先判断当前数字串是否为空,如果为空,则将当前组合字符串添加到
combinations
中,并返回。 - 如果数字串不为空,取出数字串的第一个数字
digit
,找到对应的字母串letters
。 - 遍历字母串中的每一个字母
letter
,将当前字母添加到当前组合字符串combination
的末尾,并递归调用backtrack
函数,传入剩余的数字串和更新后的组合字符串。 - 在递归调用完成后,要将当前添加的字母从组合字符串中移除,以便尝试其他字母。
- 最后,返回
combinations
列表。
3. 复杂度
- 时间复杂度:O(3^N × 4^M),其中 N 是输入数字中对应 3 个字母的数目(比如数字 2、3、4、5、6、8),M 是输入数字中对应 4 个字母的数目(比如数字 7、9),N+M 是输入数字的总数。在最坏情况下,每个数字对应 4 个字母,对于每个数字,都需要尝试 4 个字母中的 3 个字母,因此总时间复杂度为 O(3^N × 4^M)。
- 空间复杂度:O(N+M),其中 N 是输入数字中对应 3 个字母的数目,M 是输入数字中对应 4 个字母的数目。递归调用栈的深度取决于输入数字串的长度。
4.Code
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
class Solution {
// 定义数字与字母的映射关系
private final Map<Character, String> phoneMap = new HashMap<>() {{
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> combinations = new ArrayList<>();
if (digits.length() == 0) {
return combinations;
}
backtrack(digits, 0, new StringBuilder(), combinations);
return combinations;
}
// 回溯函数
private void backtrack(String digits, int index, StringBuilder combination, List<String> combinations) {
// 当前数字串遍历结束,将当前组合字符串添加到结果列表中
if (index == digits.length()) {
combinations.add(combination.toString());
return;
}
// 获取当前数字对应的字母串
String letters = phoneMap.get(digits.charAt(index));
// 遍历当前字母串中的每个字母
for (int i = 0; i < letters.length(); i++) {
// 将当前字母添加到组合字符串的末尾
combination.append(letters.charAt(i));
// 递归调用,处理下一个数字
backtrack(digits, index + 1, combination, combinations);
// 在递归调用完成后,要将当前添加的字母从组合字符串中移除,以便尝试其他字母
combination.deleteCharAt(combination.length() - 1);
}
}
}
这段代码实现了根据给定的数字字符串生成所有可能的字母组合。
欢迎大家后台联系讨论。
(一份Java面试宝典,有兴趣的读者姥爷可以私信我领取!!!免费滴)