1. 程式人生 > 實用技巧 >LeetCode刷題記錄-39

LeetCode刷題記錄-39

解題思路:一開始不知道怎麼下手,暴力遍歷也沒有合適的方法。參考了題解,瞭解到回溯演算法,結合他人的程式碼,寫了出來

借用題解的決策樹圖:

 1     //參考了題解的回溯演算法
 2     public static List<List<Integer>> combinationSum(int[] candidates, int target) {
 3         //最終結果res
 4         List<List<Integer>> res = new ArrayList<>();
 5         //
類似二叉樹遍歷的指標,不過它儲存了“當前路徑” 6 ArrayList<Integer> track = new ArrayList<>(); 7 //遍歷所謂的“決策樹” 8 calc(0, candidates, track, res, target); 9 return res; 10 11 } 12 13 /** 14 * 15 * @param start 為了防止每次遞迴都從candidates[0]開始查詢 16
* @param candidates 候選陣列 17 * @param track 遍歷的軌跡,可以看成一種“帶有遍歷軌跡的,遍歷二叉樹的指標” 18 * @param res 最終提交結果 19 * @param target 目標之和 20 */ 21 private static void calc(int start, int[] candidates, ArrayList<Integer> track, List<List<Integer>> res, int target) {
22 //計算“當前路徑”的和 23 int sum = 0; 24 for (int i = 0; i < track.size(); i++) { 25 sum += track.get(i); 26 } 27 //遞迴的退出條件 28 if (sum == target) { 29 res.add(new ArrayList<>(track)); 30 return; 31 } 32 //選擇樹,i = start 防止每次遞迴都從candidates[0]開始查詢,這樣也能考慮自身的重複 33 for (int i = start; i < candidates.length; i++) { 34 //所謂的“剪枝”,減少遞迴次數,只有candidates[i] + sum <= target才有可能存在答案 35 if (candidates[i] + sum <= target) { 36 //嘗試性加入一個候選元素 37 track.add(candidates[i]); 38 //遞迴呼叫,要麼成功找到滿足題目要求的路徑,要麼失敗,什麼也不做;不管成功失敗,接下來都要:撤銷最新的(嘗試性加入一個候選元素的)選擇 39 calc(i, candidates, track, res, target); 40 //撤銷最新的(嘗試性加入一個候選元素的)選擇,進入下一次for迴圈,尋找新的路徑 41 track.remove(track.size() - 1); 42 } 43 } 44 }

執行結果: