[组合总和 && 组合总和II][中等][递归\回溯]

208 阅读2分钟

组合总和

题目

39. 组合总和 - 力扣(LeetCode) (leetcode-cn.com)

image.png

思路

  • 将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)

题目

image.png

思路

这道题和上面那道题的区别就是,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;
};