Day 22 回溯演算法 part01

12点不睡觉还想干啥?發表於2024-07-24

77. 組合

我的這個解法還算挺簡單易懂的,還是看註釋

class Solution {
    List<List<Integer>> ans = new ArrayList(); //儲存最終結果集合
    List<Integer> tmp = new ArrayList(); //記錄單次的path
    public List<List<Integer>> combine(int n, int k) {
        backTracking(n, k);
        return ans;
    }

    public void backTracking(int n, int k){ //從1~n挑選k個陣列合的方法
        if(n < k) return;  //若k > n 顯然,不存在這樣的組合
        if(k == 1){  //從n個數中挑選一個
            for(int i = n; i > 0; i--){  //對於1~n任選一個新增到結果中即可
                tmp.add(i);
                ans.add(new ArrayList(tmp));
                tmp.remove(tmp.size()-1); //回溯
            }
            return;
        }
        //這裡也可以新增剪枝,即n == k的時候,直接放入結果即可
        //k > 1的情況,還可以分成兩種
        //1. 選擇n,再從n-1中選擇k-1個數字
        tmp.add(n);
        backTracking(n-1, k-1);
        tmp.remove(tmp.size()-1);
		//2. 不選n,從n-1中選擇k個即可
        backTracking(n-1, k);
    }
}

216. 組合總和 III

與上一題的做法差不太多,但是剪枝的操作我考慮的並不完整。這裡使用

class Solution {
    List<List<Integer>> ans = new ArrayList();
    List<Integer> path = new ArrayList();
    public List<List<Integer>> combinationSum3(int k, int n) {
        backTracking(1, k, n);
        return ans;
    }

    public void backTracking(int start, int k, int sum){ //start代表了現在可以取的第一個數字
        // sum代表了還需要加多少才能符合條件
        if(path.size() > k || sum < 0) return; //sum < 0 代表當前組合的和大於目標值了
        if(path.size() == k) {
            if(sum == 0) ans.add(new ArrayList(path));
            return;
        }
        for(int i = start; i <= 9; i++){ //所有的回溯都可以抽象成樹結構(多叉樹)
            //for迴圈相當於對每個子節點進行訪問,只有訪問到葉子節點才進行儲存結果,也就是遞迴的出口
            path.add(i);
            backTracking(i+1, k, sum-i);
            path.remove(path.size()-1);
        }
    }
}

17. 電話號碼的字母組合

class Solution {
    List<String> res = new ArrayList();
    StringBuilder sb = new StringBuilder();
    String[] map = new String[]{"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
    public List<String> letterCombinations(String digits) {
        if(digits.length() == 0) return res;
        backTracking(digits, 0);
        return res;
    }
    public void backTracking(String digits, int index){ //index代表當前要處理的數字在digits中的index
        if(sb.length() == digits.length()) {
            res.add(sb.toString());
            return;
        }
        int digit = digits.charAt(index) - '0';
        String s = map[digit];
        for(char c: s.toCharArray()){
            sb.append(c);
            backTracking(digits, index+1);
            sb.deleteCharAt(sb.length()-1);
        }
    }
}

相關文章