组合总和|||
题目:找出所有相加之和为 n 的 k 个数的组合,且满足下列条件:
只使用数字1到9
每个数字 最多使用一次
返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。
思路:先根据题目抽象成一个多叉树,然后按照要求收集结果即可
class Solution {
public List<List<Integer>> combinationSum3(int k, int n) {
List<List<Integer>> res = new ArrayList<>();
List<Integer> path = new ArrayList<>();
backtracking(k,n,0,1,path,res);
return res;
}
private void backtracking(int k,int n,int sum,int startIndex,List<Integer> path,List<List<Integer>> res){
if(path.size() == k){// 终止条件 当收集的路径大小等于k的时候就可以返回了
if(n == sum){
res.add(new ArrayList<>(path));
}
}
for(int i = startIndex;i<=9;i++){// 每一层从startIndex遍历开始收集路径
sum+=i;// 累加和
path.add(i);// 收集这一层的元素
backtracking(k,n,sum,i+1,path,res);
// 回溯
sum-=i;
path.remove(path.size()-1);
}
}
}
剪枝
class Solution {
public List<List<Integer>> combinationSum3(int k, int n) {
List<List<Integer>> res = new ArrayList<>();
List<Integer> path = new ArrayList<>();
backtracking(k,n,0,1,path,res);
return res;
}
private void backtracking(int k,int n,int sum,int startIndex,List<Integer> path,List<List<Integer>> res){
// 剪枝
if(sum > n){
return;
}
if(path.size() == k){// 终止条件 当收集的路径大小等于k的时候就可以返回了
if(n == sum){
res.add(new ArrayList<>(path));
}
}
// 剪枝
// 已经收集了path.size()个元素,还需要收集k-path.size()
// 例如 k=5,path.size() = 2,还需要收集3个元素,那么下面的循环的i从8开始就没有意义了,因为即使从8开始,后面最多也就收集到2个元素了(8,9),不够3个了,所有i要<7
int lastIndex = 9 - (k-path.size()) + 1;
for(int i = startIndex;i<=lastIndex;i++){// 每一层从startIndex遍历开始收集路径
sum+=i;// 累加和
path.add(i);// 收集这一层的元素
backtracking(k,n,sum,i+1,path,res);
// 回溯
sum-=i;
path.remove(path.size()-1);
}
}
}
电话号码的字母组合
题目:给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
思路:先抽象成多叉树,然后寻找终止条件,已经回溯的点
class Solution {
public List<String> letterCombinations(String digits) {
List<String> res = new ArrayList<>();
if(digits == null || digits.length() == 0){
return res;
}
String[] strArr = new String[]{"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
StringBuilder path = new StringBuilder();
backtracking(digits,0,path,res,strArr);
return res;
}
// index表示递归到digits的那个数字了
private void backtracking(String digits,int index,StringBuilder path,List<String> res,String[] strArr){
if(index == digits.length()){
res.add(path.toString());
return;
}
// 单层递归
String s = strArr[digits.charAt(index) - '0'];
for(int i = 0;i<s.length();i++){
// 收集当前层数据
path.append(s.charAt(i));
backtracking(digits,index + 1,path,res,strArr);
// 回溯
path.deleteCharAt(path.length() - 1);
}
}
}