电话号码的字母组合
题目链接:电话号码的字母组合
分析:
- 第一次接触回溯的题目,没有什么头绪,题目看似简单,本以为简单的多重for循环即可搞定,仔细思考发现各种问题
- 首先digits.length是可变的,那么对于digits的每一位数字,我们都需要到另一个字符串数组中查询可选字符,所以,我们需要digits.length重循环语句,简单的for循环的嵌套,是处理不了的,而深度递归可以。
- 没有达到目标层数继续递归,达到层数,则找到了一个可行解,追加至结果集,达到第i层时,我们进行遍历第i层所有可能取值的情况,进行递归,递归结束后要回到上一层,选择一个同级的下一个字符,这里递归自动弹栈,但是我们应当清除之前追加的该层的字符。
//定义数组对应的数组,回溯和解题的函数都要用到,定义为静态
static String[] manue = {"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
//定义一个暂存的字符串,用于记录每种结果
static StringBuffer sb = new StringBuffer();
public List<String> letterCombinations(String digits) {
//回溯算法
//直接进行多层循环不可行是因为,digits的长度未知,而需要的是digits.length 次循环遍历进行匹配
//定义一个结果集
List<String> result = new ArrayList<String>();
//没有输入就返回空
if(digits==null||digits.length()==0) {
return result;
}
//目标递归层数
int len = digits.length();
//调用回溯
traceback(manue,0,result,len,digits);
return result;
}
public void traceback(String[] manue,int i,List<String> result,int n,String digits) {
//已经达到递归的目标层数
if(i>=n) {
//此时sb为一个满足条件的字符串,追加至结果集
result.add(sb.toString());
return;
}
//当前层有几种可选择的字符,遍历
for(int j=0;j<manue[digits.charAt(i)-'0'].length();j++) {
//追加第j个字符
sb.append(manue[digits.charAt(i)-'0'].charAt(j));
//当前层已经选择完毕,继续进行下一层递归
traceback(manue,i+1,result,n,digits);
//删掉追加的字符,选择同级的下一个字符,相当于返回到上一层,使用另一个同级字符
sb.deleteCharAt(sb.length()-1);
}
}