程式碼隨想錄演算法訓練營,9月19日 | 39. 組合總和,40.組合總和II,131.分割回文串

漪欢酒發表於2024-09-19

39. 組合總和
題目連結:39. 組合總和
文件講解︰程式碼隨想錄(programmercarl.com)
影片講解︰組合總和
日期:2024-09-19

想法:組合總和型別題,允許重複使用元素,遞迴不+1就行。
Java程式碼如下:

class Solution {
    List<Integer> path = new ArrayList<>();
    List<List<Integer>> res = new ArrayList<>();
    public void backTracking(int[] candidates, int target, int startIndex){
        if(target < 0){
            return;
        }
        if(target == 0){
            res.add(new ArrayList(path));
            return;
        }
        for(int i = startIndex; i < candidates.length; i++){
            path.add(candidates[i]);
            target -= candidates[i];
            backTracking(candidates, target, i);
            path.removeLast();
            target += candidates[i];
        }
    }
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        backTracking(candidates, target, 0);
        return res;
    }
}

40.組合總和II
題目連結:40.組合總和II
文件講解︰程式碼隨想錄(programmercarl.com)
影片講解︰組合總和II
日期:2024-09-19

想法:去重挺麻煩,第一遍沒思路。
Java程式碼如下:

class Solution {
    List<Integer> path = new ArrayList<>();
    List<List<Integer>> res = new ArrayList<>();
    boolean[] used;
    public void backTracking(int[] candidates, int target, int startIndex){
        if(target < 0) return;
        if(target == 0){
            res.add(new ArrayList(path));
            return;
        }
        for(int i = startIndex; i < candidates.length; i++){
            if(i > 0 && candidates[i] == candidates[i - 1] && used[i - 1] == false){
                continue;
            }
            path.add(candidates[i]);
            used[i] = true;
            target -= candidates[i];
            backTracking(candidates, target, i + 1);
            path.removeLast();
            target += candidates[i];
            used[i] = false;
        }
    }
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        used = new boolean[candidates.length];
        Arrays.fill(used, false);
        Arrays.sort(candidates);
        backTracking(candidates, target, 0);
        return res;
    }
}

總結:使用boolean used陣列來表示陣列中元素用沒用,先將陣列排序,使同樣的數字在一起,uesd陣列巧妙就巧妙在,如果used[i-1]為true,說明現在的i是在樹枝上,used[i-1]為false,說明i現在是在同一樹層上,這時判斷candidates[i] == candidates[i - 1]就能直到是不是在同一層用過前一個相同大小的數了,做到了去重。在理解了用used陣列的基礎上就可以考慮不用它:

class Solution {
    List<Integer> path = new ArrayList<>();
    List<List<Integer>> res = new ArrayList<>();
    public void backTracking(int[] candidates, int target, int startIndex){
        if(target < 0) return;
        if(target == 0){
            res.add(new ArrayList(path));
            return;
        }
        for(int i = startIndex; i < candidates.length; i++){
            if(i > startIndex && candidates[i] == candidates[i - 1]){
                continue;
            }
            path.add(candidates[i]);
            target -= candidates[i];
            backTracking(candidates, target, i + 1);
            path.removeLast();
            target += candidates[i];
        }
    }
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        Arrays.sort(candidates);
        backTracking(candidates, target, 0);
        return res;
    }
}

在(橫向)同一層的時候需要判斷前一個數是否和現在的相等,而遞迴(縱向)時就正常i+1往下走就行。

131.分割回文串
題目連結:131.分割回文串
文件講解︰程式碼隨想錄(programmercarl.com)
影片講解︰分割回文串
日期:2024-09-19

想法:構成樹的思路,橫向,切一刀,從不同位置從左到右,縱向每一層在之前切一刀的位置的後面加1刀。
Java程式碼如下:

class Solution {
    List<List<String>> res = new ArrayList<>();
    List<String> path = new ArrayList<>();

    private void backtracking(String s, int startIndex, StringBuilder sb){
        if (startIndex >= s.length()){
            res.add(new ArrayList<>(path));
            return;
        }
        for (int i = startIndex; i < s.length(); i++){
            sb.append(s.charAt(i));
            if (check(sb)){
                path.add(sb.toString());
                backtracking(s, i + 1, new StringBuilder());
                path.removeLast();
            }
        }
    }

    private boolean check(StringBuilder sb){
        for(int i = 0, j = sb.length() - 1; i < j; i++, j--){
            if(sb.charAt(i) != sb.charAt(j)) return false;
        }
        return true;
    }

    public List<List<String>> partition(String s){
        backtracking(s, 0, new StringBuilder());
        return res;
    }

}

總結:判斷迴文雙指標。

相關文章