题目大意:给定一组候选数(C)(无重复)和目标数(T),找到候选数与T相加的C中的所有独特组合。 的相同重复数目可以选自c无限次数。
注意:
- 所有数字(包括目标)将为正整数。
- 解决方案集不能包含重复的组合。
例如,给定候选集[2, 3, 6, 7]
和目标7
,
A解集是:
[ [7], [2,2,3] ]动态规划法: 保存已解决的子问题的答案,而在需要时再找出已求得的答案,这样就可以避免大量的重复计算,节省时间 。 适合于用动态规划法求解的问题,经分解后得到的 子问题往往不是互相独立 的(即下一个子阶段的求解是建立在上一个子阶段的解的基础上,进行进一步的求解。
算法设计如下:含答案分析
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
*
* 动态规划法
*
*/
public class Solution {
public static List<List<Integer>> combinationSum(int[] candidates, int target) {
Arrays.sort(candidates); // 升序排列
List<List<List<Integer>>> dp = new ArrayList<>();
for (int i = 1; i <= target; i++) { // run through all targets from 1 to target
List<List<Integer>> newList = new ArrayList<>(); // combs for curr i
// run through all candidates <= i
for (int j = 0; j < candidates.length && candidates[j] <= i; j++) {
// special case when curr target is equal to curr candidate
if (i == candidates[j])
newList.add(Arrays.asList(candidates[j]));
// if current candidate is less than the target use prev results
else
for (List<Integer> l : dp.get(i - candidates[j] - 1)) {
if (candidates[j] <= l.get(0)) {
System.out.println(candidates[j]+" "+l.get(0));
List<Integer> cl = new ArrayList<>();
cl.add(candidates[j]);
cl.addAll(l);
System.out.println(cl);
newList.add(cl);
}
}
}
System.out.println(newList);
dp.add(newList);
}
return dp.get(target - 1);
}
public static void main(String[] args) {
int [] nums={2, 3, 6, 7};
int target=7;
System.out.println(combinationSum(nums,target));
}
}
结果输出:
[]
[[2]]
[[3]]
2 2
[2, 2]
[[2, 2]]
2 3
[2, 3]
[[2, 3]]
2 2
[2, 2, 2]
3 3
[3, 3]
[[2, 2, 2], [3, 3], [6]]
2 2
[2, 2, 3]
[[2, 2, 3], [7]]
[[2, 2, 3], [7]]
读者可以依据题目输出进行分析本题中动态规划算法的使用方式