|
| 1 | +```text |
| 2 | +题目: 给定一个无重复元素的数组candidates和一个目标数target,找出candidates中所有可以使数字和为target的组合; |
| 3 | + candidates 中的数字可以无限制重复被选取; |
| 4 | + 说明: |
| 5 | + 所有数字(包括 target)都是正整数; |
| 6 | + 解集不能包含重复的组合; |
| 7 | + 示例 1: |
| 8 | + 输入:candidates=[2,3,6,7],target=7,所求解集为: |
| 9 | + [ |
| 10 | + [7], |
| 11 | + [2,2,3] |
| 12 | + ] |
| 13 | +1.递归回溯法: |
| 14 | + [1]思路: |
| 15 | + (1)使用递归方式,则需要先考虑递归方法参数: |
| 16 | + 1)给定的候选数组(candidates)和目标数(target)必不可少; |
| 17 | + 2)由于最终返回嵌套集合,则嵌套结果集需要在所有递归方法中传递; |
| 18 | + 3)嵌套结果集的内部集合需要在递归方法中不断添加数,因此内部结果集也需要; |
| 19 | + (2)由于使用的是递归,因此递归方法中要考虑递归的终止条件; |
| 20 | + (3)再就是考虑什么情况下添加符合条件的集合到结果集中,什么时候需要进行递归操作; |
| 21 | + (4)由于是回溯法,需要在遍历中递归,当不满足条件时才可尝试下一个再递归测试; |
| 22 | + [2]实现: |
| 23 | + class Solution { |
| 24 | + public static List<List<Integer>> combinationSum(int[] candidates, int target) { |
| 25 | + List<List<Integer>> result = new ArrayList<>(); |
| 26 | + backtrack(candidates, result, target, new ArrayList<>(), 0); |
| 27 | + return result; |
| 28 | + } |
| 29 | + // 递归回溯 |
| 30 | + private static void backtrack(int[] candidates, List<List<Integer>> result, |
| 31 | + int target, List<Integer> list, int start) { |
| 32 | + // 递归的终止条件 |
| 33 | + if (target < 0) { |
| 34 | + return; |
| 35 | + } |
| 36 | + // 符合条件时,添加到结果集中 |
| 37 | + if (target == 0) { |
| 38 | + // 该list全局独一份,添加结果集时需要拷贝添加 |
| 39 | + result.add(new ArrayList<>(list)); |
| 40 | + } else { |
| 41 | + for (int i = start; i < candidates.length; i++) { |
| 42 | + list.add(candidates[i]); |
| 43 | + backtrack(candidates, result, target - candidates[i], list, i); |
| 44 | + // 由下一层级回溯到该层级,说明该层级加入的元素不符合条件 |
| 45 | + //(符合条件的在子层级已经添加到结果集了) |
| 46 | + list.remove(list.size() - 1); |
| 47 | + } |
| 48 | + } |
| 49 | + } |
| 50 | + } |
| 51 | + [3]复杂度分析: |
| 52 | + (1)时间复杂度: O(N^H),N为数组长度,H为最大递归深度 |
| 53 | + (2)空间复杂度: O(N) |
| 54 | +``` |
0 commit comments