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

示例: 输入:"23" 输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
说明:尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。
思路
从示例上来说,输入"23",最直接的想法就是两层for循环遍历了吧,正好把组合的情况都输出了。
如果输入"233"呢,那么就三层for循环,如果"2333"呢,就四层for循环.......
就是这for循环的层数如何写出来,此时又是回溯法登场的时候了。
理解本题后,要解决如下三个问题:
- 数字和字母如何映射
- 两个字母就两个for循环,三个字符我就三个for循环,以此类推,然后发现代码根本写不出来
- 输入1 * #按键等等异常情况
回溯法来解决n个for循环的问题
例如:输入:"23",抽象为树形结构,如图所示:

图中可以看出遍历的深度,就是输入"23"的长度,而叶子节点就是我们要收集的结果,输出["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"]。
回溯三部曲:
- 确定回溯函数参数
首先需要一个字符串s来收集叶子节点的结果,然后用一个字符串数组result保存起来,这两个变量我依然定义为全局。
再来看参数,参数指定是有题目中给的string digits,然后还要有一个参数就是int型的index。
这个index是记录遍历第几个数字了,就是用来遍历digits的(题目中给出数字字符串),同时index也表示树的深度。
- 确定终止条件
例如输入用例"23",两个数字,那么根节点往下递归两层就可以了,叶子节点就是要收集的结果集。
那么终止条件就是如果index 等于 输入的数字个数(digits.size)了(本来index就是用来遍历digits的)。
然后收集结果,结束本层递归。
- 确定单层遍历逻辑
首先要取index指向的数字,并找到对应的字符集(手机键盘的字符集)。
然后for循环来处理这个字符集
本题每一个数字代表的是不同集合,也就是求不同集合之间的组合
class Solution {
List<String> res=new ArrayList<>();
public List<String> letterCombinations(String digits) {
if(digits==null|| digits.length()==0){
return res;
}
//初始对应所有的数字,为了直接对应2-9,新增了两个无效的字符串""
String[] strArr={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
process(strArr,digits,0);
return res;
}
//每次迭代获取一个字符串,所以会设计大量的字符串拼接,所以这里选择更为高效的 StringBuilder
StringBuilder path=new StringBuilder();
private void process(String[] strArr,String digits,int index){
if(index==digits.length()){
res.add(path.toString());
return;
}
int strIndex=digits.charAt(index)-'0';
//str 表示当前strIndex对应的字符串
String str=strArr[strIndex];
for(int i=0;i<str.length();i++){
path.append(str.charAt(i));
process(strArr,digits,index+1);
path.deleteCharAt(path.length()-1);
}
}
}
class Solution {
List<String> ans=new ArrayList<>();
public List<String> letterCombinations(String digits) {
if(digits.length()==0){
return ans;
}
//初始对应所有的数字,为了直接对应2-9,新增了两个无效的字符串""
String[] strArr={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
String[] arr=new String[digits.length()];
for(int i=0;i<digits.length();i++){
arr[i]=strArr[digits.charAt(i)-'0'];
}
List<Character> path=new ArrayList<>();
process(arr,0,path);
return ans;
}
private void process(String[] arr,int index, List<Character> path){
if(index==arr.length){
ans.add(getPath(path));
return;
}
for(int i=0;i<arr[index].length();i++)
{
List<Character> pick=new ArrayList<>(path);
pick.add(arr[index].charAt(i));
process(arr,index+1,pick);
}
}
private String getPath(List<Character> path){
StringBuilder sb=new StringBuilder();
for(Character c:path){
sb.append(c);
}
return sb.toString();
}
}
class Solution {
List<String> ans=new ArrayList<>();
public List<String> letterCombinations(String digits) {
if(digits.length()==0){
return ans;
}
//初始对应所有的数字,为了直接对应2-9,新增了两个无效的字符串""
String[] strArr={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
String[] arr=new String[digits.length()];
for(int i=0;i<digits.length();i++){
arr[i]=strArr[digits.charAt(i)-'0'];
}
process(arr,0);
return ans;
}
StringBuilder path=new StringBuilder();
private void process(String[] arr,int index){
if(index==arr.length){
ans.add(path.toString());
return;
}
for(int i=0;i<arr[index].length();i++)
{
path.append(arr[index].charAt(i));
process(arr,index+1);
path.deleteCharAt(path.length()-1);
}
}
}

浙公网安备 33010602011771号