回溯之组合总和III

        分享完组合总和I组合总和II,这次分享组合总和III,下面先给出回溯的模板代码。

private void backtracking(参数1,参数2,...){
	if(递归终止条件){
		收集结果;
		return;
	}
	for(遍历集合){
		处理;
		backtracking(参数1,参数2,...); // 递归;
		回溯;
	}
}


组合总和III

找出所有相加之和为 n 的 k 个数的组合,且满足下列条件:只使用数字1到9每个数字最多使用一次返回所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。

示例 1:
输入: k = 3, n = 7
输出: [[1,2,4]]
解释:1 + 2 + 4 = 7,没有其他符合的组合了。

class Solution {
    List<List<Integer>> ans = new ArrayList<>();
    List<Integer> path = new ArrayList<>();
    int sum = 0;
    public List<List<Integer>> combinationSum3(int k, int n) {
        backtracking(k, n, 1);
        return ans;
    }
    void backtracking(int k, int n, int startIndex){
        if(sum > n) return;
        if(sum == n && path.size() == k){
            ans.add(new ArrayList<>(path));
            return;
        }
        for(int i = startIndex;i <= 9;i++){
            path.add(i);
            sum += i;
            backtracking(k, n, i + 1);
            path.remove(path.size() - 1);
            sum -= i;
        }
    }
}

        代码中首先定义了ans集合用于收集所有等于n的组合,path用于收集递归遍历过程中添加的元素,如果path中的元素组合符合要求,将path中的元素组合放入ans中,同时定义sum用于记录path中的元素和。combinationSum3方法中调用backtracking方法,最后返回ans集合。以上述示例说明backtracking方法的具体执行流程。
        进入backtracking,sum等于0,不满足两个if判断,进入for循环,startIndex从1开始,将1放入path中,path为[1],sum等于1,递归进入下一个backtracking,sum等于1不满足两个if条件,startIndex从2开始,将元素2加入到path中,path为[1, 2],sum等于3,递归进入下一个backtracking,sum等于3不满足两个if条件,startIndex从3开始,将元素3加入到path中,path为[1, 2, 3],sum等于6,递归进入下一个backtracking,sum等于6不满足两个if条件,startIndex从4开始,将元素4加入到path中,path为[1, 2, 3, 4],sum等于10,递归进入下一个backtracking,sum > n,递归返回上一个backtracking,将元素4从path中移除,path为[1, 2, 3],sum等于6,for循环继续,i++,将元素5放入path中,path为[1, 2, 3, 5],sum等于11,递归进入下一个backtracking,sum > n,递归返回上一个backtracking,同理将元素5移除,将元素6加入,递归进入下一个backtracking,也会由于sum > n递归返回,将元素6移除,将7放入path,递归进入下一个backtracking,由于sum > n递归返回。接着是[1, 2, 3, 8],[1, 2, 3, 9],都会由于sum > n递归返回,最后的[1, 2, 3, 9]递归返回后,将元素9从path中移除,最后path为[1, 2, 3],之后i++等于数组长度,for循环结束,递归返回上一个backtracking,将元素3从path中移除,for循环继续,i++,将元素4加入到path中,path为[1, 2, 4],sum等于7,递归进入下一个backtracking中,sum = n,满足条件,将[1, 2, 4]加入到ans中,如此重复上述过程,即可得到所有符合条件的组合。
        下面给出上述代码执行过程的部分图示。
请添加图片描述
        所有遍历结果为:
[1, 2, 3, 4]
[1, 2, 3, 5]
[1, 2, 3, 6]
[1, 2, 3, 7]
[1, 2, 3, 8]
[1, 2, 3, 9]
[1, 2, 4]
[1, 2, 5]
[1, 2, 6]
[1, 2, 7]
[1, 2, 8]
[1, 2, 9]
[1, 3, 4]
[1, 3, 5]
[1, 3, 6]
[1, 3, 7]
[1, 3, 8]
[1, 3, 9]
[1, 4, 5]
[1, 4, 6]
[1, 4, 7]
[1, 4, 8]
[1, 4, 9]
[1, 5, 6]
[1, 5, 7]
[1, 5, 8]
[1, 5, 9]
[1, 6, 7]
[1, 6, 8]
[1, 6, 9]
[1, 7]
[1, 8]
[1, 9]
[2, 3, 4]
[2, 3, 5]
[2, 3, 6]
[2, 3, 7]
[2, 3, 8]
[2, 3, 9]
[2, 4, 5]
[2, 4, 6]
[2, 4, 7]
[2, 4, 8]
[2, 4, 9]
[2, 5, 6]
[2, 5, 7]
[2, 5, 8]
[2, 5, 9]
[2, 6]
[2, 7]
[2, 8]
[2, 9]
[3, 4, 5]
[3, 4, 6]
[3, 4, 7]
[3, 4, 8]
[3, 4, 9]
[3, 5]
[3, 6]
[3, 7]
[3, 8]
[3, 9]
[4, 5]
[4, 6]
[4, 7]
[4, 8]
[4, 9]
[5, 6]
[5, 7]
[5, 8]
[5, 9]
[6, 7]
[6, 8]
[6, 9]
[7, 8]
[7, 9]
[8]
[9]

  • 34
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回溯法求解组合总和的主要思路是:对于每个数字,可以选择使用或不使用,如果使用了,则将其加入当前组合中,并继续考虑剩下的数字;如果不使用,则直接考虑剩下的数字。当目标值减为0时,说明已经找到了一个符合要求的组合。 以下是一个求解组合总和的JavaScript代码示例: ```javascript function combinationSum(candidates, target) { const res = []; candidates.sort((a, b) => a - b); // 排序 backtrack([], 0, target); return res; function backtrack(path, start, target) { if (target < 0) return; // 如果目标值小于0,说明不符合要求,结束当前回溯 if (target === 0) { // 如果目标值等于0,说明已经找到了一个符合要求的组合 res.push([...path]); return; } for (let i = start; i < candidates.length; i++) { path.push(candidates[i]); // 将当前数字加入组合中 backtrack(path, i, target - candidates[i]); // 继续考虑剩下的数字 path.pop(); // 回溯,将当前数字从组合中移除 } } } ``` 在代码中,backtrack函数用于进行回溯。它接受三个参数:当前组合path、起始数字的下标start和目标值target。在函数中,遍历候选数字数组,对于每个数字,有两种选择:使用或不使用。如果使用,将其加入当前组合path,继续考虑剩下的数字;如果不使用,直接考虑剩下的数字。当目标值减为0时,说明已经找到了一个符合要求的组合,将其加入结果数组res中,并退出当前回溯

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值