【LeetCode】组合与组合总和

之前讲解了使用试探-回溯法求解全排列,我们都学过排列组合,其中的组合也是非常适合用试探-回溯法解决的问题。本文节选了LeetCode上两道组合的题目,并给出了使用试探-回溯策略的解法。

组合

题目描述

给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。
你可以按 任何顺序 返回答案。

题目链接:https://leetcode.cn/problems/combinations

解答思路

与全排列类似,使用试探-回溯的策略。只是在调用回溯函数的时候有选择和不选两种情况。

代码

function combine(n: number, k: number): number[][] {
    const result: number[][] = [];
    const array = new Array(n).fill(0).map((_, i) => i + 1);
    const res: number[] = [];

    const backtrack = (cur: number) => {
        // 抵达总数量,返推入结果
        if (res.length === k) {
            result.push([...res]);
            return;
        }
        if (cur === n) return;
        // 选择该数
        res.push(array[cur]);
        backtrack(cur + 1);
        // 不选该数
        res.pop();
        backtrack(cur + 1);
    }
    // 从index为0的数开始计算
    backtrack(0);

    return result;
};

组合总和

题目描述

给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。
candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。

题目链接:https://leetcode.cn/problems/combination-sum/description

解答思路

与上面一题类似,但是这里要以总和为target为结束条件,所以递归的时候要带上当前累积的总和(或者剩余的数值)作为待检验的对象。这里调用backtrack同样有两种情况,一种是选择当前数字(注意此时index不递增,以支持可重复选择的情况),另一种是不选当前数字。

代码

function combinationSum(candidates: number[], target: number): number[][] {
    const result: number[][] = [];
    const res: number[] = [];
    const backtrack = (left: number, index: number) => {
        if (index === candidates.length) return;
        if (left === 0) {
            // 剩余需要找的值为0,则找到一个结果
            result.push([...res]);
            return;
        }
        // 不选当前数字,index增加
        backtrack(left, index + 1);
        if (left - candidates[index] >= 0) {
            // 选当前数字,index不变
            res.push(candidates[index]);
            backtrack(left - candidates[index], index);
            res.pop();
        }
    }
    backtrack(target, 0);
    return result;
};
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值