法1:回溯
想法:
- 40.组合总和Ⅱ是JavaScript|LeetCode|搜索|39.组合总和的“变式”
- 两者的解法基本相同,观察39.与40.的题目描述区别,给代码增加相应的限制
- “candidates 中的每个数字在每个组合中只能使用一次。”
- “解集不能包含重复的组合”
所以:1)仍然将candidates降序排列;2)当前数字加入组合后,将当前数字之后的数字进行组合,以得到target-当前数字;3)优先使排在前面的数字当前组合的第一个数字,后面与这个数字相同的数字,不能成为当前组合的第一个数字(剪枝,事先排除重复的组合)
/**
* @param {number[]} candidates
* @param {number} target
* @return {number[][]}
*/
var combinationSum2 = function(candidates, target) {
var output = [], temp = [];
candidates.sort(function(a, b) {return b - a;});
// 将candidates中数字降序排列
var i = 0;
for(i = 0; i < candidates.length; i++) {
if(candidates[i] > target) {
continue;
}
if(i - 1 >= 0 && candidates[i] == candidates[i - 1]) {
continue;
}
temp.push(candidates[i]);
doCombinationSum(candidates.slice(i + 1), target - candidates[i], temp, output);
temp.pop();
}
return output;
};
function doCombinationSum(candidates, target, temp, output) {
if(target == 0) {
output.push(temp.concat([]));
return;
}
var i = 0;
for(i = 0; i < candidates.length; i++) {
if(candidates[i] > target) {
continue;
}
if(i - 1 >= 0 && candidates[i] == candidates[i - 1]) {
continue;
}
temp.push(candidates[i]);
doCombinationSum(candidates.slice(i + 1), target - candidates[i], temp, output);
temp.pop();
}
}