题目来源
17. 电话号码的字母组合
题目思路
从示例上来说,输入"23",最直接的想法就是两层for循环遍历了吧,正好把组合的情况都输出了。
如果输入"233"呢,那么就三层for循环,如果"2333"呢,就四层for循环…
理解本题后,要解决如下三个问题:
- 1.数字和字母如何映射
- 2.两个字母就两个for循环,三个字符我就三个for循环,以此类推,然后发现代码根本写不出来
- 3.输入1 * #按键等等异常情况
数字和字母如何映射
String[] numString = {"", //0
"", //1
"abc", //2
"def", //3
"ghi", //4
"jkl", //5
"mno", //6
"pqrs", //7
"tuv", //8
"wxyz"}; //9
回溯法来解决n个for循环的问题
回溯
回溯三部曲:
- 1.确定回溯函数参数
首先需要一个字符串temp来收集叶子节点的结果,然后用一个字符串数组result保存起来,这两个变量我依然定义为全局。
再来看参数,参数指定是有题目中给的string digits,然后还要有一个参数就是int型的index。
ArrayList<String> result = new ArrayList<>();
StringBuilder temp = new StringBuilder();
backTracking(String digits,String[] numString,int index)
- 2.确定终止条件
例如输入用例"23",两个数字,那么根节点往下递归两层就可以了,叶子节点就是要收集的结果集。
那么终止条件就是如果index 等于 输入的数字个数(digits.length)了(本来index就是用来遍历digits的)。
然后收集结果,结束本层递归。
if(index == digits.length()){
result.add(temp.toString());
return;
}
- 3.确定单层遍历逻辑
首先要取index指向的数字,并找到对应的字符集(手机键盘的字符集)。
然后for循环来处理这个字符集,代码如下:
int digit = digits.charAt(index) - '0'; // 将index指向的数字转为int
String str = numString[digit]; // 取数字对应的字符集
for(int i = 0;i<str.length();i++){
temp.append(str.charAt(i)); // 处理
backTracking(digits,numString,index+1); // 递归,注意index+1,一下层要处理下一个数字了
temp.deleteCharAt(temp.length() - 1); // 回溯
}
整体代码如下
class Solution {
ArrayList<String> result = new ArrayList<>();
StringBuilder temp = new StringBuilder();
public List<String> letterCombinations(String digits) {
if(digits == null || digits.length() < 1){
return result;
}
String[] numString = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
backTracking(digits,numString,0);
return result;
}
public void backTracking(String digits,String[] numString,int index){
if(index == digits.length()){
result.add(temp.toString());
return;
}
int digit = digits.charAt(index) - '0'; // 将index指向的数字转为int
String str = numString[digit]; // 取数字对应的字符集
for(int i = 0;i<str.length();i++){
temp.append(str.charAt(i)); // 处理
backTracking(digits,numString,index+1); // 递归,注意index+1,一下层要处理下一个数字了
temp.deleteCharAt(temp.length() - 1); // 回溯
}
}
}