之前利用回溯解决组合、子集、全排列、分割问题和组合总和问题,这次再分享一道利用回溯解决的leetcode题,下面先给出回溯的模板代码。
private void backtracking(参数1,参数2,...){
if(递归终止条件){
收集结果;
return;
}
for(遍历集合){
处理;
backtracking(参数1,参数2,...); // 递归;
回溯;
}
}
电话号码的字母组合
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按任意顺序返回。给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例 1:
输入:digits = “23”
输出:[“ad”,“ae”,“af”,“bd”,“be”,“bf”,“cd”,“ce”,“cf”]
class Solution {
Map<Character, String> map;
List<String> ans = new ArrayList<>();
StringBuffer path = new StringBuffer();
public List<String> letterCombinations(String digits) {
if(digits.length() == 0) return ans;
map = new HashMap<>();
map.put('2', "abc");
map.put('3', "def");
map.put('4', "ghi");
map.put('5', "jkl");
map.put('6', "mno");
map.put('7', "pqrs");
map.put('8', "tuv");
map.put('9', "wxyz");
backtracking(digits, 0);
return ans;
}
private void backtracking(String digits,int startIndex){
if(digits.length() == path.length()){
ans.add(path.toString());
return;
}
String str = map.get((digits.charAt(startIndex)));
for(int i = 0;i < str.length();i++){
path.append(str.charAt(i));
backtracking(digits, startIndex + 1);
path.delete(path.length() - 1, path.length());
}
}
}
首先定义map用来存储数字所对应的字母,定义ans用于收集结果,定义path用于收集递归for循环遍历加入的字母,如果path中的字母组合符合要求,将其加入ans中。在letterCombinations方法中将数字2-9及其对应字母存储到map中,之后调用backtracking方法收集所有可能的组合,最后返回ans。
以上述示例说明backtracking代码的执行流程。进入backtracking,startIndex为0,path长度为0,不满足if条件,通过map.get方法获取了字符串digits中的第一个数字2,str为abc,进入for循环,将a放入path中,path为a,递归进入下一个backtracking,之后path长度为1,不满足if条件,startIndex为1,获取字符串digits的第二个数字3,str为def,进入for循环,将str的第一个字母d加入到path中,path为ad,递归进入下一个backtracking,此时path长度与digits长度相等,将ad加入到ans中,递归返回上一个backtracking中,将d从path中删除,path为a,for循环继续,将e加入到path中,path为ae,递归进入下一个backtracking,此时path长度与digits长度相等,将ae加入到ans中,递归返回上一个backtracking中,将e从path中删除,path为a,for循环继续,将f加入到path中,path为af,递归进入下一个backtracking,此时path长度与digits长度相等,将af加入到ans中,递归返回上一个backtracking中,将f从path中删除,path为a,for循环结束,递归返回最初的backtracking,将a从path中删除,path为空,for循环继续,将b加入到path中,path为b,如此重复上述步骤,就可以得到所有符合要求的字母组合。
下面给出上述代码递归和回溯图。