回溯——电话号码的字母组合

题目:

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

这道题是回溯算法的经典入门题,核心思路是:遍历每个数字对应的字母,递归拼接所有可能的组合,直到拼接完所有数字,就得到一个完整结果。

代码核心解析

1. 数字-字母映射
数组存储映射关系,数组索引对应电话按键数字,值对应字母,查询效率最高:

  • 索引0、1:空字符串(无对应字母)
  • 索引2~9:分别对应abc、def、ghi、jkl、mno、pqrs、tuv、wxyz

2. 回溯算法逻辑
回溯的核心是“选一个字母->递归->回退”:

1、终止条件:当遍历到数字的最后一位(index==数字长度),将当前拼接的字符串加入结果列表。

2、递归过程:
取出当前数字对应的所有字母:
遍历每个字母,拼接到当前字符串后,递归处理下一个数字
递归返回后,自动“回退’(因为拼接是新字符串,无需手动撤销)。

3、边界处理
如果输入为空字符串""直接返回空列表,避免空指针异常。

总结

  1. 核心解法: 回溯算法,适合处理这种“多步骤、多选择求所有组合的问题”;
  2. 关键步骤: 建立数字字母映射+递归拼接+终止条件判断;
  3. 时间复杂度: O(3m×4n)(m 是对应 3 个字母的数字个数,n 是对应 4 个字母的数字个数);
  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
整个过程就是:

  1. 先选 2 对应的字母:a
  2. 去 3 里面选:d、e、f
    → 得到 ad, ae, af
  3. 回到 2,再选 b
  4. 去 3 里面选:d、e、f
    → bd, be, bf
  5. 回到 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 letterCombinations(String digits) {
List result = new ArrayList<>();
//边界条件:输入为空字符串,直接返回空列表
if(digitsnull||digits.length()0){
return result;
}
//回溯:当前拼接的字符串、输入数字、结果列表、当前遍历到的数字索引
backtrack("",digits,result,0);
return result;
}

//回溯核心方法
private void backtrack(String currentStr,String digits,List result, int index){
//递归终止条件:遍历完所有数字,当前字符串就是一个完整组合
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);
}
}
}

posted @ 2026-04-26 14:59  ZealousMclaren  阅读(13)  评论(0)    收藏  举报