题目

image.png

思路

  • 思路一:dfs+回溯,遇到这一类相同元素不计算顺序的问题,我们在搜索的时候就需要按某种顺序搜索。具体的做法是:每一次搜索的时候设置 下一轮搜索的起点 index
  • 思路二:dfs+回溯+剪枝
  • 思路三:其实这个问题类似于零钱兑换 II问题,因此可以转换为完全背包问题,但是用来找组合不方便,还是dfs+回溯比较方便

    代码

    1. //错误写法
    2. public List<List<Integer>> combinationSum(int[] candidates, int target) {
    3. List<List<Integer>> res = new ArrayList<>();
    4. dfs(candidates, target, 0, res, new ArrayList<>());
    5. return res;
    6. }
    7. public void dfs(int[] candidates, int target, int index, List<List<Integer>> res, List<Integer> tmp) {
    8. if (0 == target) res.add(new ArrayList<>(tmp));
    9. if (target <= 0) return;
    10. for (int i = index; i < candidates.length; i++) {
    11. tmp.add(candidates[i]);
    12. //失败写法在index,不更新会导致重复结果,用不同起点确保了不会重复
    13. dfs(candidates, target - candidates[i], index, res, tmp);
    14. tmp.remove(tmp.size() - 1);
    15. }
    16. }
    17. //1.dfs+回溯
    18. public List<List<Integer>> combinationSum(int[] candidates, int target) {
    19. List<List<Integer>> res = new ArrayList<>();
    20. dfs(candidates, target, 0, res, new ArrayList<>());
    21. return res;
    22. }
    23. public void dfs(int[] candidates, int target, int index, List<List<Integer>> res, List<Integer> tmp) {
    24. if (0 == target) res.add(new ArrayList<>(tmp));
    25. if (target <= 0) return;
    26. for (int i = index; i < candidates.length; i++) {
    27. tmp.add(candidates[i]);
    28. dfs(candidates, target - candidates[i], i, res, tmp);
    29. tmp.remove(tmp.size() - 1);
    30. }
    31. }
    32. //2.dfs+回溯+剪枝
    33. public List<List<Integer>> combinationSum(int[] candidates, int target) {
    34. List<List<Integer>> res = new ArrayList<>();
    35. //排序方便剪枝
    36. Arrays.sort(candidates);
    37. dfs(candidates, target, 0, res, new ArrayList<>());
    38. return res;
    39. }
    40. public void dfs(int[] candidates, int target, int index, List<List<Integer>> res, List<Integer> tmp) {
    41. if (0 == target) res.add(new ArrayList<>(tmp));
    42. if (target <= 0) return;
    43. for (int i = index; i < candidates.length; i++) {
    44. //小于时就剪枝
    45. if (target < candidates[i]) return;
    46. tmp.add(candidates[i]);
    47. dfs(candidates, target - candidates[i], i, res, tmp);
    48. tmp.remove(tmp.size() - 1);
    49. }
    50. }

    组合总和