题目描述
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
题目连接
测试样例
输入:digits = “23”
输出:[“ad”,“ae”,“af”,“bd”,“be”,“bf”,“cd”,“ce”,“cf”]
输入:digits = “”
输出:[]
输入:digits = “2”
输出:[“a”,“b”,“c”]
解题思路
- 首先将字母与字符串对应起来,eg:2对应abc
- 可以用HashMap
- 也可以用数组
- 考虑怎么解这个题,最简单的想法,for循环暴力求解
- 存在问题:如果是"23"的话,两层for循环,“246”的话三重for循环
- for循环没有规律可循
- 所以考虑通过
回溯
的方法暴力求解- 回溯方式是递归的,也是暴力求解
- 只是帮我们确定了我们要嵌套几个for循环
- 例如,输入n个数字的话,嵌套n个for循环
- 回溯算法求解可以抽象为树形结构
- 树结构如下
- 树的深度由输入数字的个数决定,第一层递归从第一个数字中取数,第二层递归从第二个数字中取数……
- 树的宽度由每个数字对应的字母长度控制:2对应的分支树对应的宽度是3
代码实现
class Solution {
//给定数字,方面寻找它对应的字符串
Map<Character, String> telMap = new HashMap<Character, String>(){
{
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,注意后面是ArrayList
List<String> result = new ArrayList<String>();
if(digits.length() == 0){
return result;
}
backtrack(digits, 0, new StringBuilder(), result);
return result;
}
//回溯
//传入参数:待遍历的字符串、当前需要遍历的是字符串中的第几个元素、用来记录当前操作的字符串、待返回的结果List
public void backtrack(String digits, int index, StringBuilder oneresult, List<String> result){
//记录当前digits中待遍历的数据长度
// int len = digits.length() - index;
//如果当前index等于字符串digits(题目中给的“234”)的长度,则代表该oneresult已经符合要求(包含了digits长度的字符),应该将oneresult加入带返回的结果中
//回溯终止条件,收获结果!注意指向的是digits.length(),而不是digits.length()-1,因为在digits.length()-1时候,还是存在一个数字的,eg:23,digits.length()-1代表的是指向3,仍应该有个搜索过程,所以应该指向3的下一位,也就是digits.length()
if(index == digits.length()){
result.add(oneresult.toString());
}
//否则,代表digits中的元素没有遍历完,需要继续遍历
else{
//记录当前digits中的元素
char nowNum = digits.charAt(index);
//找到当前数字对应的字符串
String numTel = telMap.get(nowNum);
//对字符串进行遍历!
for(int j = 0; j < numTel.length(); j++){
//将该数字对应的字符加到oneresult后面
oneresult.append(numTel.charAt(j));
//该数字后面还可能有数字,应当将后面的数字对应的字符也加到oneresult中,回溯
//此时,index应为当前index+1,因为当前index的字符已经加到了oneresult中。index指目前处理的是传入数字组合中的数字下标,即下层递归,需要处理index+1处的数字
backtrack(digits, index+1, oneresult, result);
//回溯过程。需要弹出去,将ad变成a,重新取e,变为ae。
//https://www.bilibili.com/video/BV1yV4y1V7Ug/?spm_id_from=333.337.search-card.all.click&vd_source=0d2a9b4260ce977e642d073c6ee2260d
oneresult.deleteCharAt(index);
}
}
}
}
注意问题
回溯过程,需要弹出去oneresult.deleteCharAt(index);