【Leetcode】39.组合总和 题解

题目

给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的数字可以无限制重复被选取。

说明:

所有数字(包括 target)都是正整数。
解集不能包含重复的组合。

示例 1:

输入:candidates = [2,3,6,7], target = 7,
所求解集为:
[
[7],
[2,2,3]
]
示例 2:

输入:candidates = [2,3,5], target = 8,
所求解集为:
[
[2,2,2,2],
[2,3,3],
[3,5]
]

提示:

1 <= candidates.length <= 30
1 <= candidates[i] <= 200
candidate 中的每个元素都是独一无二的。
1 <= target <= 500

题目链接

思路

这一题很容易想到用递归来解决,采用递归就要确定递归的边界和操作。

先看递归操作,很简单,就是遍历candidates数组,每次从中取出一个元素加入存储当前结果的集合中。

再看递归边界,边界为:

  • 当结果集合的元素和大于target时,直接返回
  • 当结果集合的元素和等于target时,将结果集合加入总结果的集合再返回

但是直接这样写会出现一个问题:总结果集中会出现重复元素。观察递归树:

每次添加元素时,只需要从当前元素的后面开始考虑,前面都已经枚举过了。所以还需要递归当前元素的下标。

代码

class Solution {
    private List<List<Integer>> result = new ArrayList<>();

    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        ArrayList<Integer> res = new ArrayList<>();
        cal(0, candidates, res, target, 0);
        return result;
    }

    private void cal(int start, int[] candidates, ArrayList<Integer> res, int target, int sum) {
        if(sum > target)
            return;
        if(sum == target) {
            result.add(new ArrayList<>(res));//这里要构造一个新的
            return;
        }
        for (int i = start; i < candidates.length; i++) {
            res.add(candidates[i]);
            cal(i, candidates, res, target, sum + candidates[i]);
            res.remove(res.size() - 1);
        }
    }
}

注意在添加元素时,要new数组。

猜你喜欢

转载自blog.csdn.net/qq_41279172/article/details/108273639