leetcode-zgd-day25-216.组合总和III/17.电话号码的字母组合

100 阅读2分钟

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);
         }
     }
 }