回溯笔记-[39]组合总和

回溯

一般用于寻找满足某个条件的组合或者路径。可以已理解为对一棵树进行深度优先遍历,能走则走,不能走则回头选择另一条路走。回溯的关键点是,每一步有几种选择,以及怎么选择。

题目

分析

需要求所有无重复的组合,而且每个数可以选择多次。

一般对于求无重复组合问题的解法是对数组元素进行顺序遍历,每次选择数字都会面临两个选择:

  1. 选择当前数字,若数字可重复选择,则下一次还可以继续选当前数字;

  1. 不选择当前数字,且永远后续从下一个数字开始选择。

因此,每次需要进行两个选择,即进行两次不同的递归调用。

class Solution {
    //
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        List<List<Integer>> res = new ArrayList();
        List<Integer> tmpRes = new ArrayList();
        cb(candidates, 0, target, res, tmpRes, 0);
        return res;
    }

    private void cb(int[] candidates, int i, int target, List<List<Integer>> res, List<Integer> tmpRes, int sum) {
        if (sum == target) {
            res.add(new ArrayList<>(tmpRes)); 
            // 此处的tmp是引用,需要创建一个新的列表保存结果,否则后续tmpRes进行元素增减会影响res中的结果
            return;
        }
        if (sum > target) {
            return;
        }
        if (i > candidates.length - 1) {
            return;
        }

        tmpRes.add(candidates[i]);
        // 选择当前数字,并且下一个数字也可以选择当前数字
        cb(candidates, i, target, res, tmpRes, sum + candidates[i]);
        tmpRes.remove(tmpRes.size() - 1);
        // 不选当前数字, 之后也都不会再选择当前数字
        cb(candidates, i + 1, target, res, tmpRes, sum);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值