leetcode-zgd-day27-39.组合总和/40.组合总和II/131.分割回文串

67 阅读2分钟

39.组合总和

题目链接:39. 组合总和 - 力扣(LeetCode)

解题思路:

 class Solution {
 ​
     List<List<Integer>> ans = new ArrayList<>();
     List<Integer> path = new LinkedList<>(); // 因为path设计到经常修改,所以用LinkedList
 ​
     public List<List<Integer>> combinationSum(int[] candidates, int target) {
         Arrays.sort(candidates); // 先进行排序
         backTracking(candidates, target, 0);
         return ans;
     }
     public void backTracking(int[] candidates, int target, int startIndex){ // startIndex为了避免输出重复结果
         if(target == 0){ // 回溯的终止条件
             ans.add(new ArrayList<>(path));
             return;
         }
         for(int i = startIndex; i < candidates.length; i++){
             if(candidates[i] > target) return;
             path.add(candidates[i]);
             backTracking(candidates, target - candidates[i], i);
             path.remove(path.size() - 1);
         }
     }
 }

40.组合总和II

题目链接:40. 组合总和 II - 力扣(LeetCode)

解题思路:

 class Solution {
 ​
     List<List<Integer>> ans = new ArrayList<>();
     List<Integer> path = new LinkedList<>();
 ​
     public List<List<Integer>> combinationSum2(int[] candidates, int target) {
         // used数组是为了记录哪个元素使用过了。
         boolean[] used = new boolean[candidates.length];
         Arrays.fill(used, false);
         // 这个排序是为了后续去重方便,不然输出的结果中会有重复解出现。因为数组中的数字是不唯一的
         Arrays.sort(candidates);
         backTracking(candidates, target, used, 0);
         return ans;
     }
     public void backTracking(int[] candidates, int target, boolean[] used, int startIndex){
         if(target == 0){ // 结束条件
             ans.add(new ArrayList<>(path));
             return;
         }
         for(int i = startIndex; i < candidates.length; i++){
             if(candidates[i] > target) return;
             if(used[i] == true) continue;
             // 这里的去重是为了去除[1,1,2,5] target = 8 这种数组中的两组1 2 5的情况
             if (i > 0 && candidates[i] == candidates[i - 1] && !used[i - 1]) {
                 continue;
             }
             used[i] = true;
             path.add(candidates[i]);
             backTracking(candidates, target - candidates[i], used, i);
             used[i] = false;
             path.remove(path.size() - 1);
         }
     }
 }

131.分割回文串

题目链接:131. 分割回文串 - 力扣(LeetCode)

解题思路:

首先是错误代码: backTracking里面的逻辑没有理清楚

 class Solution {
 ​
     List<List<String>> ans = new ArrayList<>();
     List<String> path = new LinkedList<>();
 ​
     public List<List<String>> partition(String s) {
         backTracking(s, 0);
         return ans;
     }
     public void backTracking(String s, int startIndex){
         if(startIndex >= s.length()){ //结束条件
             ans.add(new ArrayList<>(path));
             return;
         }
         for(int i = startIndex; i < s.length(); i++){
             //开始剪枝
             for(int j = i + 1; j <= s.length(); j++){
                 if(!ishw(s.substring(i,j))) continue;
                 path.add(s.substring(i,j));
                 backTracking(s, j);
                 path.remove(path.size() - 1);
             }
         }
     }
     public boolean ishw(String s){
         int i = 0, j = s.length() - 1;
         while(i < j){
             if(s.charAt(i) == s.charAt(j)){
                 i++;
                 j--;
             }
             else return false;
         }
         return true;
     }
 }

关键部分如下:

 //  public void backTracking(String s, int startIndex){
 //      if(startIndex >= s.length()){ //结束条件
 //          ans.add(new ArrayList<>(path));
 //          return;
 //      }
         for(int i = startIndex; i < s.length(); i++){
             //开始剪枝
             for(int j = i + 1; j <= s.length(); j++){
                 if(!ishw(s.substring(i,j))) continue;
                 path.add(s.substring(i,j));
                 backTracking(s, j);
                 path.remove(path.size() - 1);
             }
         }
 //  }

我在这里套了两层for循环,为了得到符合条件的回文字符串,这样显然是错误的,错误的根本在于没有搞清楚startIndex到底是用来干嘛的。因为本题目中的要求是进行拆分,也就是说startIndex这个起始位置在下一次拆分的时候必须是分割的起点,但是如果像上述两层for循环来做的话,只不过是让起点从startIndex开始而已,这个思路显然是错误的。

正确的代码如下:

 class Solution {
 ​
     List<List<String>> ans = new ArrayList<>();
     List<String> path = new LinkedList<>();
 ​
     public List<List<String>> partition(String s) {
         backTracking(s, 0);
         return ans;
     }
     public void backTracking(String s, int startIndex){
         if(startIndex >= s.length()){ //结束条件
             ans.add(new ArrayList<>(path));
             return;
         }
         for(int i = startIndex; i < s.length(); i++){
             //如果是回文子串,则记录
             if (ishw(s.substring(startIndex, i + 1))) {
                 String str = s.substring(startIndex, i + 1);
                 path.add(str);
             } else {
                 continue;
             }
             //起始位置后移,保证不重复
             backTracking(s, i + 1);
             path.remove(path.size() - 1);
         }
     }
     public boolean ishw(String s){
         int i = 0, j = s.length() - 1;
         while(i < j){
             if(s.charAt(i) == s.charAt(j)){
                 i++;
                 j--;
             }
             else return false;
         }
         return true;
     }
 }