216.组合总和III
完成
思路:
按照上一题组合总和
的逻辑,代码逻辑是一样的,只不过多了一个sum的判断。
代码
未做剪枝
注意,res在添加path时一定要创建新对象,否则添加的是path的引用,会跟着path变化。
class Solution {
public List<List<Integer>> res = new ArrayList<>();
public List<Integer> path = new ArrayList<>();
int sum = 0;
public List<List<Integer>> combinationSum3(int k, int n) {
backtracking(k, n, 1);
return res;
}
public void backtracking(int k, int n, int startIndex){
// 这里需要sum 和 size共同限定
// 否则会出现数量不对,但sum满足条件的情况
if(sum == n && path.size() == k){
// 这里一定要创建新对象,否则添加的是引用
res.add(new ArrayList<>(path));
return;
}
for (int i = startIndex; i <= 9; i++) {
path.add(i);
sum+=i;
backtracking(k, n, i+1);
path.removeLast();
sum-=i;
}
}
}
现在考虑做剪枝。可以从几个方面入手。
sum > n
之后的情况都不必考虑- 由于遍历是从小到大的,之后添加的值会越来越大,明显不满足条件的值可以不考虑。
class Solution {
public List<List<Integer>> res = new ArrayList<>();
public List<Integer> path = new ArrayList<>();
int sum = 0;
public List<List<Integer>> combinationSum3(int k, int n) {
backtracking(k, n, 1);
return res;
}
public void backtracking(int k, int n, int startIndex){
// 这里需要sum 和 size共同限定
// 否则会出现数量不对,但sum满足条件的情况
if(sum == n && path.size() == k){
res.add(new ArrayList<>(path));
return;
}
// 剪枝
if(sum > n){
return;
}
for (int i = startIndex; i <= 9; i++) {
// 剪枝,后面的元素都太大了
if(n-sum<startIndex) return;
path.add(i);
sum+=i;
backtracking(k, n, i+1);
path.removeLast();
sum-=i;
}
}
}
17.电话号码的字母组合
完成
思路:
画出树形图比较好分析,树的宽度是digits[0]
对应字符串的各字符遍历,深度是digits 的长度。
特别注意的是,在递归回溯函数时,跟之前的i+1
不同,这里需要的是index+1
代码
class Solution {
public String[] map = {
"", //0
"", //1
"abc", //2
"def", //3
"ghi", //4
"jkl", //5
"mno", //6
"pqrs", //7
"tuv", //8
"wxyz", //9
};
public List<String> res = new ArrayList<>();
public StringBuilder path = new StringBuilder();
public List<String> letterCombinations(String digits) {
if(digits.length() == 0 || digits == null) return res;
backtracking(digits, 0);
return res;
}
public void backtracking(String digits, int index){
if(path.length() == digits.length()){
res.add(path.toString());
return;
}
String str = map[digits.charAt(index)-'0'];
for (int i = 0; i < str.length(); i++) { // 遍历宽度,遍历map中取出的字符串长度
path.append(str.charAt(i));
// 这里不是i+1,是index+1,每次递归是从map中取新的字符串遍历
backtracking(digits, index+1);
path.deleteCharAt(path.length()-1);
}
}
}