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     }

运行结果:

 

posted @ 2020-07-20 21:27  细雨轻风  阅读(134)  评论(0编辑  收藏  举报