组合总和
题目
39. 组合总和 - 力扣(LeetCode) (leetcode-cn.com)
思路
- 将candidates数组进行从小到大的顺序排列
- 求解target的数组的问题可以分解为求解target - candidates[i] 的数组 加上 candidates[i]
- 按照上面的思路,将target拆分成小的target,直到target为0, 将此时的数据加入到答案
- 如果target不为0,那么就继续遍历数组,如果遇到candidates[i] > target, 可以直接结束循环,因为后序的candidates[i] 必定大于target,是无效的。
- 为了避免出现重复,面对更深一层的candidates的选择,不能比进入到这一层所选择的数字candidates[i]小(这样可以保证答案数组里面的数字也是从小到大进行排列的,不会出现重复),表现在函数里面就是begin参数的设置
- 还需要注意的是,在本层函数结束的时候,记得把进入本层所取的candidates[i]的值pop出去。
代码
/**
* @param {number[]} candidates
* @param {number} target
* @return {number[][]}
*/
var combinationSum = function(candidates, target) {
candidates.sort((a, b)=>(a-b))
let answer = [], last_arr =[];
let dfs = (t, begin)=>{
if(t === 0){
answer.push(Array.from(last_arr));
}else{
for(let i = begin; i < candidates.length; i++){
if(candidates[i] > t){
break;
}
last_arr.push(candidates[i])
dfs(t - candidates[i], i);
}
}
last_arr.pop();
}
dfs(target, 0);
return answer;
};
组合总和的改编:组合总和2
40. 组合总和 II - 力扣(LeetCode) (leetcode-cn.com)
题目
思路
这道题和上面那道题的区别就是,candidates数组里面有重复元素,同时解集里面不可以有重复的组合。大体的解决思路和上面类似,就是首先将数组排序,然后将求解target的问题,转化为求解target - candidates[i]的问题;需要注意的细节是,在每层遍历的时候,需要判断一下,当前遍历到的元素,和本层所遍历到的,当前元素的上一个元素,是否相同,如果相同,那么就不选择当前的这个candidates[i], 而是继续去查找下面的元素。这个需要注意的地方,可以实现组合的去重,即在当前这个位置,已经选择了值为val的元素,当下面遍历到的元素还是val的时候,就不去选择这个val了,而是去选择其他还没有选择过的元素,来填充当前的位置。
代码
var combinationSum2 = function(candidates, target) {
let answer = [];
let len = candidates.length;
let dfs = (index, t, arr)=>{
if(t == 0){
answer.push(Array.from(arr));
}else{
for(let i = index; i < len; i++){
if(t < candidates[i]){
break;
}else{
// 主要是在这里和上面有区别
if(i == index || candidates[i] != candidates[i-1]){
arr.push(candidates[i]);
dfs(i + 1, t - candidates[i], arr);
arr.pop();
}
}
}
}
}
candidates.sort((a, b) => (a - b))
dfs(0, target, []);
return answer;
};