216.组合总和III
题目链接:216. 组合总和 III - 力扣(LeetCode)
解题思路:
回溯法组合题目
该题目审题得知,只能使用数组1-9,并且不允许数字有重复。
1.回溯的结束条件:
path数组中够k个数字并且和为n,题目中是扣减n的方式,所以条件为n等于0
2.回溯函数的返回值和输入参数:
不需要返回值,因为是向数组中插入结果。
输入参数,需要额外的startIndex让下层回溯函数知道数字使用到哪了。最开始还打算再创建一个sum,来记录当前path的和,不过发现这个是多余的参数,这个功能完全可以由n来代替。
3.回溯的剪枝:
如果后面剩余的元素个数和path中的元素个数全都加上也不够k个的时候,就说明后面都不可能了,剪枝剪掉即可。
回溯到某处时,还需要(k - path.size())个元素,最大的数是9,所以从当前数字到9至少还得有(k - path.size())个元素
也就是说,最后一个符合条件的元素是9-(k - path.size())+1。比他大的所有数字都不可能组成符合要求的数组了。
class Solution {
List<List<Integer>> ans = new ArrayList<>();
List<Integer> path = new LinkedList<>();
public List<List<Integer>> combinationSum3(int k, int n) {
combinhelper(k, n, 1);
return ans;
}
public void combinhelper(int k, int n, int startIndex){
if(path.size() == k){
if(n == 0){
ans.add(new ArrayList<>(path));
}
return;
}
for(int i = startIndex; i <= 9 - (k - path.size()) + 1; i++){ // 注意剪枝
path.add(i);
combinhelper(k, n - i, i + 1);
path.remove(path.size() - 1);
}
}
}
17.电话号码的字母组合
题目链接:17. 电话号码的字母组合 - 力扣(LeetCode)
解题思路:
1.频繁的字符串操作应使用StringBuilder
2.StringBuilder的api StringBuilder.append() StringBuilder.deleteCharAt() 这个是删除指定索引字符,StringBuilder.delete(a,b) a和b是索引下标,删除这个区间
3.构建String[]的时候 是{"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"},而不是["","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"]
4.想清楚这个题的index是做什么用的。
class Solution {
List<String> ans = new ArrayList<>();
StringBuilder sbpath = new StringBuilder();
public List<String> letterCombinations(String digits) {
if(digits == null || digits.length() == 0) return ans;
String[] record = {"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
combinHelper(digits, record, 0);
return ans;
}
public void combinHelper(String digits,String[] record, int index){
// index 是用来记录当前遍历到那个数字了
if(sbpath.length() == digits.length()){ // 这里的结束条件也可以是 index == digits.length()
ans.add(sbpath.toString());
return;
}
// 获取当前数字对应的按键字符
String s = record[digits.charAt(index) - '0'];
for(int i = 0; i < s.length(); i++){ // 横向遍历 例如"wxyz"
sbpath.append(s.charAt(i));
combinHelper(digits, record, index + 1); // 纵向递归 遍历下一个数字对应的字符串去
sbpath.deleteCharAt(sbpath.length() - 1);
}
}
}