216.组合总和III
选取过程:
K相当于树的深度,9相当于树的宽度,和为4
class Solution {
List<Integer> path=new ArrayList<>();
List<List<Integer>> result=new ArrayList<>();
public List<List<Integer>> combinationSum3(int k, int n) {
backtracking(n, k, 0, 1);//第一个backtracking,sum=0,startIndex=1
return result;
}
public void backtracking(int targetSum,int k,int sum,int startIndex){
//终止条件
if(path.size()==k){
//如果path的大小和k一样,check sum是否和目标和一样
if(sum==targetSum){
result.add(new ArrayList<>(path));
}
return;
}
//横向遍历
for(int i=startIndex;i<=9;i++){
sum=sum+i;//更新和
path.add(i);//更新路径
backtracking(targetSum,k,sum,i+1);//纵向遍历
sum=sum-i;//回溯
//删除最后一个元素
path.remove(path.size()-1);
}
}
}
单层遍历逻辑:
● 第一层递归:初始startIndex=1,选取1,path加入1,变为[1],sum为1.
○ 调用backtracking(…,2),即从2开始寻找剩下的数加入组合。
● 第二层递归:这里开始遍历i的值从2开始。
○ 当i=2,path加入2,变为[1, 2],sum=3。满足条件(path.size() == k),再判断和是否满足=4?并不满足,不加入到result里,但是终止。此时sum-2=1,path变回[1]
○ 当i=3,path加入3,变为[1, 3],此时sum满足条件=4,将[1, 3]添加到result中,然后移除3,sum-3再次回到1,path回到[1]。
○ 当i=4,path加入4,变为[1, 4],sum=5不满足和为4的条件,然后移除4,path回到[1],sum-4=1
○ …
● 回到第一层递归:完成所有i=1时的递归,移除1,path变回[]。
● i=2的递归开始:此时从2开始重复上述过程,直到遍历完所有可能的组合。
电话号码组合
思路:回溯法解决n个for循环的问题
字母与数字的映射,可以定义一个map
三部曲
● 确定回溯参数
○ 需要传入数字串,index记录遍历到第几个数字(题目中的数字字符串)
● 确定终止条件
○ index=digits.size(两个数字就是两个字母,三个数字就是三个字母)
● 单层逻辑
○ 根据数字取出对应的字符
○ for循环遍历字母
○ 取字母组合
○ 回溯
class Solution {
List<String> result=new ArrayList<>();
StringBuilder path = new StringBuilder();
public List<String> letterCombinations(String digits) {
//空串判断
if("".equals(digits)){
return result;
}
backtracking(digits,0);
return result;
}
/**
* 回溯
* @param digits 数字字符串
* @param index 当前的数字
*/
public void backtracking(String digits,int index){
if(index==digits.length()){
result.add(path.toString());
return;
}
String digit=String.valueOf(digits.charAt(index));
String letters=findLetter(digit);//查询每个数字对应的字符集
for(int i=0;i<letters.length();i++){
path.append(letters.charAt(i));
backtracking(digits, index+1);
path.deleteCharAt(path.length()-1);
}
}
/**
* 键盘字典
* @param number 数字
* @return 对应的字母
*/
private String findLetter(String number){
Map<String,String> tel=new HashMap<>();
tel.put("2", "abc");
tel.put("3", "def");
tel.put("4", "ghi");
tel.put("5", "jkl");
tel.put("6", "mno");
tel.put("7", "pqrs");
tel.put("8", "tuv");
tel.put("9", "wxyz");
if(tel.containsKey(number)){
return tel.get(number);
}
return "";
}
}