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
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/combination-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:
找出target的所有组合记为f(target),以target=7为例,
f(5) + 2 表示target=5的所有组合,并在每个组合中添加2元素
因此,f(7)可以表示为:
f(7) = (f(5) + 2) + (f(4) + 3) + (f(1) + 6) + (f(0) + 7)
但需要注意,f(5)+2 的组合中(2 + 3)+ 2 与 f(4)+3 组合中的 (2+2)+3 是重复的,因此计算 f(7) 的结果时要去重。具体实现如下:
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
class Solution {
public static Map<Integer, List<List<Integer>>> resultMap = new HashMap<Integer, List<List<Integer>>>(); // 记录target结果,避免重复计算
/**
* 主函数
*
* @param args
*/
public static void main(String[] args) {
// 测试
int[] candidates = {2,3,5};
int target = 8;
List<List<Integer>> result = combinationSum(candidates, target);
for(int i = 0; i < result.size(); i++) {
for(int j=0; j < result.get(i).size(); j++) {
System.out.print(result.get(i).get(j)+"\t");
}
System.out.println("\n");
}
}
public static List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> result = new ArrayList<List<Integer>>(); // 当前结果
Set<List<Integer>> resultSet = new HashSet<List<Integer>>(); // 用于记录当前的已存入结果,用set方便快速查找
if (target < 0) {
return result;
}
for (int i = 0; i < candidates.length; i++) {
List<List<Integer>> subResult;
int subTarget = target - candidates[i];
if (resultMap.containsKey(subTarget)) { // 已记录结果可提前返回
subResult = resultMap.get(subTarget);
}
if(subTarget == 0) {
List<Integer> tmp = new ArrayList<Integer>();
tmp.add(candidates[i]);
result.add(tmp);
}
else{
subResult = combinationSum(candidates, subTarget);
if (!subResult.isEmpty()) {
for (List<Integer> t : subResult) {
t.add(candidates[i]);
Collections.sort(t);
// 加入时判断是否在当前结果中有重复
if (!resultSet.contains(t)) {
result.add(t);
resultSet.add(t);
}
}
}
}
}
resultMap.put(target, result);
return result;
}
}