回溯解决组合问题

1.组合(leetcode77)

给定n,k,从1-n中选择k个数

剪枝:当后续元素数量不足时,要减枝,<=n-(k-path.length)+1

var combine = function(n, k) {
    let res = [],path=[];
    function combineHelper(n,k,startIndex){
        if(path.length == k){
            res.push([...path]);
            return;
        }
        for(let i = startIndex;i<=n-(k-path.length)+1;i++){
            path.push(i);
            combineHelper(n,k,i+1);
            path.pop();
        }
    }
    combineHelper(n,k,1);
    return res;
};

2.组合总数III(leetcode216)

找出和为n的k个数,组合中只有1-9

剪枝:当后续元素数量不足时,要减枝,<=9-(k-path.length)+1

var combinationSum3 = function(k, n) {
    let path = [],res = [];
    function backtracking(start,sum){
        if(path.length == k){
            if(sum == n){
                res.push([...path]);
            }
            return;
        }
        // 减枝
        for(let i = start;i<=9-(k-path.length)+1;i++){
        // for(let i = start;i<=9;i++){
            path.push(i);
            backtracking(i+1,sum+i);
            path.pop();
        }
    }
    backtracking(1,0);
    return res;
};

3.组合总和(leetcode39)

从无重复的数组nums中,找到和target的数组

注意:数组nums中的元素可以被重复取

减枝:先排序,当nums[i]>target时,减枝

var combinationSum = function(candidates, target) {
    let res = [],path = [];
    candidates.sort();
    function backtracking(j,sum){
        if(sum > target) return;
        if(sum == target){
            res.push([...path]);
            return;
        }
        for(let i = j;i<candidates.length;i++){
            const n = candidates[i];
            if(n>target-sum) continue;
            path.push(n);
            sum += n;
            // candidates中数组可重复使用
            backtracking(i,sum);
            path.pop();
            sum -= n;
        }
    }
    backtracking(0,0);
    return res;
};

4.组合总和III(leetcode40)

从有重复的数组nums中,找到和target的数组,每个nums[i]只能用一次。Nums有重复,但res中不能有重复数组。

注意:数组nums中的元素不可以被重复取

减枝:先排序,当nums[i]>target时,减枝

去重:使用used,对树层去重

var combinationSum2 = function(candidates, target) {
    let res = [],path = [];
    let len = candidates.length;
    candidates.sort((a,b)=>a-b);
    let used = new Array(len).fill(false);
    function backtrcking(startIndex,sum){
        if(sum > target) return;
        if(sum == target){
            res.push([...path]);
            return;
        }
        for(let i = startIndex;i<len;i++){
            let cur = candidates[i];
            if(cur >  target-sum || (i>0 && candidates[i] == candidates[i-1] && !used[i-1])) continue;
            if (used[i] == true) continue;
            path.push(cur);
            sum += cur;
            used[i] = true;
            backtrcking(i+1,sum);
            path.pop();
            sum -= cur;
            used[i] = false;
        }
    }
    backtrcking(0,0);
    return res;
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值