代码随想录算法训练营第25天 | 216. 组合总和 III,17. 电话号码的字母组合
216. 组合总和 III
- 此题相比较于组合 多了一个求和的条件 就可以在终止条件中添加该条件判断
- 加一个变量sum来统计 每次递归时 的求和值 回溯时减掉
class Solution {
List<Integer> path = new ArrayList<>();
List<List<Integer>> result = new ArrayList<>();
public List<List<Integer>> combinationSum3(int k, int n) {
traversal(k,n,0,1);
return result;
}
public void traversal(int k, int n,int sum, int startIndex){
//终止条件
if(path.size()==k){
if(sum==n){
result.add(new ArrayList<>(path));
}
return;
}
//每一层递归逻辑
for(int i=startIndex; i<=Math.min(n,9);i++){
path.add(i);
sum+=i;
traversal(k,n,sum,i+1);
sum-=path.get(path.size()-1);
path.remove(path.size()-1);
}
return;
}
}
剪枝
- 每一层不需要遍历完到9 因为for循环中 i控制的是开始的位置 假如开始的位置过于靠后 那取的数就不够
- 当一层递归中 发现目前的sum已经大于目标值n 就可以停止本次递归往回了 因为再往后也取不到值
class Solution {
List<Integer> path = new ArrayList<>();
List<List<Integer>> result = new ArrayList<>();
public List<List<Integer>> combinationSum3(int k, int n) {
traversal(k,n,0,1);
return result;
}
public void traversal(int k, int n,int sum, int startIndex){
//终止条件
if(sum>n){
return;
}
if(path.size()==k){
if(sum==n){
result.add(new ArrayList<>(path));
}
return;
}
//每一层递归逻辑
for(int i=startIndex; i<=9-(k-path.size())+1;i++){
path.add(i);
sum+=i;
traversal(k,n,sum,i+1);
sum-=path.get(path.size()-1);
path.remove(path.size()-1);
}
return;
}
}
17. 电话号码的字母组合
此题是有多个集合 去遍历 所以 指针为 index 用来确定不同集合
- 回溯的本质 就是嵌套n层for循环
- 在想回溯题目解法时 可以画一下树形图
- 把输入数字 映射为对应的字母字符串
- 然后回溯三部曲
- 传入 输入数字字符串 映射数组 当前指针
- 终止条件 当index==digits长度时停止
- 从左到右获取数字
- 获取对应数字字母
- 用树形递归字母字符串 进入下一层递归时 Index+1 然后出来时 回溯
class Solution {
List<String> result = new ArrayList<>();
StringBuilder sb = new StringBuilder();
public List<String> letterCombinations(String digits) {
//当输入为空字符串时 直接返回空List
if(digits.length()==0) return result;
String[] map = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
backtracing(digits,0,map);
return result;
}
//递归函数 输入输出
public void backtracing(String digits, int index, String[] map){
//终止条件
//这个终止条件是在下一层递归的开始之前停止 所以index没问题
if(index==digits.length()){
result.add(sb.toString());
return;
}
//单层递归逻辑
//获取当前对应数字 该操作可以将字符转成int
int num = digits.charAt(index) - '0';
//获取数字对应的字母字符串
String str = map[num];
//遍历当前字母字符串
for(int i=0;i<str.length();i++){
//加入元素
sb.append(str.charAt(i));
//进入下一层递归
backtracing(digits,index+1,map);
//回溯
sb.deleteCharAt(sb.length()-1);
}
return;
}
}