回溯——电话号码的字母组合
题目:
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
这道题是回溯算法的经典入门题,核心思路是:遍历每个数字对应的字母,递归拼接所有可能的组合,直到拼接完所有数字,就得到一个完整结果。
代码核心解析
1. 数字-字母映射
用数组存储映射关系,数组索引对应电话按键数字,值对应字母,查询效率最高:
- 索引0、1:空字符串(无对应字母)
- 索引2~9:分别对应abc、def、ghi、jkl、mno、pqrs、tuv、wxyz
2. 回溯算法逻辑
回溯的核心是“选一个字母->递归->回退”:
1、终止条件:当遍历到数字的最后一位(index==数字长度),将当前拼接的字符串加入结果列表。
2、递归过程:
取出当前数字对应的所有字母:
遍历每个字母,拼接到当前字符串后,递归处理下一个数字;
递归返回后,自动“回退’(因为拼接是新字符串,无需手动撤销)。
3、边界处理
如果输入为空字符串"",直接返回空列表,避免空指针异常。
总结
- 核心解法: 回溯算法,适合处理这种“多步骤、多选择、求所有组合的问题”;
- 关键步骤: 建立数字字母映射+递归拼接+终止条件判断;
- 时间复杂度: O(3m×4n)(m 是对应 3 个字母的数字个数,n 是对应 4 个字母的数字个数);
- 空间复杂度: O(m+n)(递归栈深度,等于数字长度)。
一、代码解释: int currentNum = digits.charAt(index) - '0'
1. 拆解每一部分
digits.charAt(index)
取出数字字符串里第index个字符。
比如输入"23",index = 0时取到的时字符'2',不是数字2!
-'0'
用字符'2'减去字符'0',得到真正的数字2。
2. 核心原理:ASII码
计算机里,所有字符都有一个数字编号,叫ASCII码。
其中:
- '0' 的 ASCII 码是 48
- '1' → 49
- '2' → 50
- ...
- '9' → 57
'2' - '0' = 50 - 48 = 2 (数字)
二、 为什么必须这么写?
因为我们的映射表 KEY_MAP 是用数字当索引的:
KEY_MAP[2] = "abc"
你不能写:
KEY_MAP['2'] // 错误!'2'是字符,不是数字索引、
三、代码解释:for (char c : letters.toCharArray()) { backtrack(currentStr + c, digits, result, index + 1);}
1.先拆成2部分看
① for (char c : letters.toCharArray())
这是增强for循环,作用只有一个:
把当前数字对应的所有字母,一个一个拿出来遍历。
举个例子:
当前数字是2->对应字母"abc"
toCharArray()会把字符串变成字符数组:['a','b','c']
循环就会依次拿出a、b、c
② backtrack(...)
这是递归调用,作用:
把当前选的字母拼接到字符串后面,然后去处理下一个数字。
参数意思:
- currentStr + c:把刚才选的字母拼上去
- index + 1:去处理下一个数字
2. 用生活例子讲:就像选密码!
假设输入数字是 23
2 → abc
3 → def
整个过程就是:
- 先选 2 对应的字母:a
- 去 3 里面选:d、e、f
→ 得到 ad, ae, af - 回到 2,再选 b
- 去 3 里面选:d、e、f
→ bd, be, bf - 回到 2,再选 c
→ cd, ce, cf
两个关键方法
-
digits.charAt(index):把字符串digits中下标为index的字符取出来,
比如:
String digits = "23": digitals.charAt(0) = '2' -
letters.toChatArray():把字符串letters转换成字符数组
比如:
String letters = "abc" ; letters.toCharArray() = ['a','b','c'];
完整代码实现如下:
class Solution {
private static final String[] KEY_MAP = {
"", //0
"", //1
"abc", //2
"def", //3
"ghi", //4
"jkl", //5
"mno", //6
"pqrs",//7
"tuv", //8
"wxyz" //9
};
public List
List
//边界条件:输入为空字符串,直接返回空列表
if(digitsnull||digits.length()0){
return result;
}
//回溯:当前拼接的字符串、输入数字、结果列表、当前遍历到的数字索引
backtrack("",digits,result,0);
return result;
}
//回溯核心方法
private void backtrack(String currentStr,String digits,List
//递归终止条件:遍历完所有数字,当前字符串就是一个完整组合
if(index == digits.length()){
result.add(currentStr);
return;
}
//获取当前数字对应的字母
int currentNum = digits.charAt(index) - '0'; //字符转数字(如:'2'->2)
String letters = KTY_MAP[currentNum];
//遍历当前数字的所有字母,递归拼接下一个数字的字母
for(char c: letters.tocharArry()){
backtrack(currentStr + c,digits,result,index+1);
}
}
}
浙公网安备 33010602011771号