给定一个数集C和一个目标数T,找到C中所有和等于T的组合。C中的每个数在组合中最大只允许使用一次。
注意:
所有的数(包括目标数)都是正整数。
结果中不允许有重复组合。
例如,给定数集 [10,1,2,7,6,1,5],目标数8
[
[1,7]
[1,2,5]
[2,6]
[1,1,6]
]
public class Solution {
public static List> combinationSum2(int[] candidates, int target) {
List> result = new ArrayList>();
if (candidates == null || candidates.length == 0) {
return result;
}
Arrays.sort(candidates);
List temp = new ArrayList();
Map count = count(candidates);
combinationSum(candidates, target, count, candidates.length - 1, temp,
result);
return result;
}
private static Map count(int[] candidates) {
Map result = new HashMap();
for (Integer i : candidates) {
Integer c = result.get(i);
result.put(i, c == null ? Integer.valueOf(1) : (c + 1));
}
return result;
}
private static void combinationSum(int[] candidates, int target,
Map count, int i, List temp,
List> result) {
int c = count.get(candidates[i]);
for (int j = Math.min(target / candidates[i], c); j >= 0; j--) {
if (i == 0) {
if (target == candidates[i] * j) {
result.add(add(temp, candidates[i], j));
}
} else {
List t = add(temp, candidates[i], j);
if (target == j * candidates[i]) {
result.add(t);
} else {
int k = i - c;
if (k >= 0) {
combinationSum(candidates, target - j * candidates[i], count, k, t,
result);
}
}
}
}
}
private static List add(List temp, int x, int j) {
List t = new ArrayList(temp);
for (int k = 0; k < j; k++) {
t.add(x);
}
return t;
}
}