🎉 关注“青柠代码录”公众号,🔥更多精彩内容持续更新中🔥,快来加入我们吧!🚀
目录
今天我们将探讨一个经典的回溯算法问题——电话号码的字母组合。通过详细的解题思路、完整的 Java 代码实现以及案例执行过程分析,我们将一步步揭开这个问题的奥秘。
🌟 问题解析与背景
在现代通讯工具中,电话按键上的数字与字母映射关系是一个经典的设计。
例如,按下数字键 2
对应字母 a, b, c
,而按下 3
则对应 d, e, f
。
基于这种映射关系,给定一个仅包含数字 2-9
的字符串(即电话号码),我们需要返回所有可能的字母组合。
核心要点:
输入限制:
-
输入字符串长度范围为
[0, 4]
。 -
字符串中的每个字符都属于范围
['2', '9']
。 -
数字
1
不对应任何字母。
输出要求:
-
返回所有可能的字母组合,顺序不限。
难点分析:
-
需要处理多个数字组合时的笛卡尔积问题。
-
使用回溯算法高效生成所有组合。
🧩 解题思路
1. 构建数字到字母的映射表
首先,我们需要构建一个哈希表(或数组)来存储每个数字对应的字母集合。这是解决问题的基础数据结构。
private static final String[] KEYS = { "", // 0 "", // 1 "abc", // 2 "def", // 3 "ghi", // 4 "jkl", // 5 "mno", // 6 "pqrs", // 7 "tuv", // 8 "wxyz" // 9 };
2. 回溯法生成所有组合
回溯算法是一种递归方法,适用于解决组合问题。具体步骤如下:
终止条件:
-
如果当前索引超出了输入字符串的长度,则说明完成了一个组合,将其加入结果集。
递归逻辑:
-
获取当前数字对应的字母集合。
-
遍历该集合中的每个字母,并将其追加到当前组合中。
-
递归处理下一个数字。
3. 特殊情况处理
-
如果输入为空字符串,则直接返回空列表。
💻 Java 代码实现
以下是完整的 Java 实现代码,包含了详细注释以便于理解:
import java.util.ArrayList; import java.util.List; public class Solution { // 数字到字母的映射表 private static final String[] KEYS = { "", // 0 "", // 1 "abc", // 2 "def", // 3 "ghi", // 4 "jkl", // 5 "mno", // 6 "pqrs", // 7 "tuv", // 8 "wxyz" // 9 }; public List<String> letterCombinations(String digits) { List<String> result = new ArrayList<>(); // 处理特殊情况:输入为空字符串 if (digits == null || digits.length() == 0) { return result; } // 调用回溯函数 backtrack(digits, 0, new StringBuilder(), result); return result; } /** * 回溯函数 * @param digits 输入的数字字符串 * @param index 当前处理的数字索引 * @param current 当前的字母组合 * @param result 存储所有结果的列表 */ private void backtrack(String digits, int index, StringBuilder current, List<String> result) { // 终止条件:当索引达到字符串末尾 if (index == digits.length()) { result.add(current.toString()); return; } // 获取当前数字对应的字母集合 char digit = digits.charAt(index); String letters = KEYS[digit - '0']; // 遍历字母集合 for (char letter : letters.toCharArray()) { // 添加当前字母 current.append(letter); // 递归处理下一个数字 backtrack(digits, index + 1, current, result); // 回溯:移除最后一个字母 current.deleteCharAt(current.length() - 1); } } public static void main(String[] args) { Solution solution = new Solution(); // 测试用例 1 String digits1 = "23"; System.out.println("输入: " + digits1); System.out.println("输出: " + solution.letterCombinations(digits1)); // 测试用例 2 String digits2 = ""; System.out.println("\n输入: " + digits2); System.out.println("输出: " + solution.letterCombinations(digits2)); // 测试用例 3 String digits3 = "2"; System.out.println("\n输入: " + digits3); System.out.println("输出: " + solution.letterCombinations(digits3)); } }
🔍 案例执行过程分析
示例 1:输入 "23"
执行过程:
初始状态:
-
输入字符串:
"23"
-
当前组合:空字符串
""
-
结果列表:空列表
[]
第一步:处理数字 2
-
数字
2
对应字母集合:"abc"
-
遍历字母集合,依次尝试添加
a
,b
,c
:
-
当前组合变为:
"a"
,"b"
,"c"
第二步:处理数字 3
-
数字
3
对应字母集合:"def"
-
在每个当前组合的基础上,继续追加
d
,e
,f
:
-
"a"
→"ad"
,"ae"
,"af"
-
"b"
→"bd"
,"be"
,"bf"
-
"c"
→"cd"
,"ce"
,"cf"
最终结果:
-
所有可能的组合:
["ad","ae","af","bd","be","bf","cd","ce","cf"]
示例 2:输入 ""
执行过程:
-
输入为空字符串,直接返回空列表
[]
。
示例 3:输入 "2"
执行过程:
初始状态:
-
输入字符串:
"2"
-
当前组合:空字符串
""
-
结果列表:空列表
[]
第一步:处理数字 2
-
数字
2
对应字母集合:"abc"
-
遍历字母集合,依次添加
a
,b
,c
。
最终结果:
-
所有可能的组合:
["a","b","c"]