题目:
给定一个无重复元素的数组 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
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/combination-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
============================
思路:
1.先排序,便于剪枝
2.我们会采用递归的方式去搜索答案,需要保证后面添加到集合curList中的数字不能比之前的小,因为我升序排序了,所以很容易做到。
即:
每一层递归,都可以从排序后的candidates 的第i个元素开始搜索,但是一旦选择了元素第j个元素,此后的递归只能从j开始搜索。
代码如下:
class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
Arrays.sort(candidates);
List<List<Integer>> result = new ArrayList<>();
dfs(0,0,new LinkedList<Integer>(),result,candidates,target);
return result;
}
/**
*
* @param deep candidates数组里的下标。我觉得后面添加的元素不能比前面小
* @param curSum 当前的总和
* @param curList 当前的元素集合,用链表实现便于尾部操作
* @param result 题目的解
* @param candidates 题目给的
* @param target 题目给的
*/
private void dfs(int deep,int curSum,LinkedList<Integer> curList,List<List<Integer>> result,
int[] candidates, int target) {
for(int i=deep;i<candidates.length;i++) {
int sum = curSum + candidates[i];
if(sum > target) {
break; // 不能继续搜索了,后面的一个比一个大
}
curList.add(candidates[i]);
if(sum == target) {
result.add(new ArrayList(curList));
}
dfs(i,sum,curList,result,candidates,target);
curList.removeLast();
}
}
}