回溯——2.组合总和III

力扣题目链接

找出所有相加之和为 n 的 k 个数的组合。组合中只允许含有 1 - 9 的正整数,并且每种组合中不存在重复的数字。

说明:

  • 所有数字都是正整数。
  • 解集不能包含重复的组合。

示例 1: 输入: k = 3, n = 7 输出: [[1,2,4]]

示例 2: 输入: k = 3, n = 9 输出: [[1,2,6], [1,3,5], [2,3,4]]

解题思路

  • 目标:在1到9的数字中,找到k个不同的数字,这些数字的和等于目标值n

  • 约束条件

    1. 不能重复使用数字。
    2. 只能使用1到9之间的数字。
    3. 结果中的组合必须恰好包含k个数字。
  • 方法:使用回溯法(Backtracking)来探索所有可能的组合,并通过剪枝来减少无效的计算,从而提升效率。

完整代码如下:

class Solution:
    def combinationSum3(self, k: int, n: int) -> List[List[int]]:
        result = []  # 存放结果集
        self.backtracking(n, k, 0, 1, [], result)
        return result

    def backtracking(self, targetSum, k, currentSum, startIndex, path, result):
        if currentSum > targetSum:  # 剪枝操作
            return  # 如果path的长度等于k但currentSum不等于targetSum,则直接返回
        if len(path) == k:
            if currentSum == targetSum:
                result.append(path[:])
            return
        for i in range(startIndex, 9 - (k - len(path)) + 2):  # 剪枝
            currentSum += i  # 处理
            path.append(i)  # 处理
            self.backtracking(targetSum, k, currentSum, i + 1, path, result)  # 注意i+1调整startIndex
            currentSum -= i  # 回溯
            path.pop()  # 回溯
def combinationSum3(self, k: int, n: int) -> List[List[int]]:
    result = []  # 存放结果集
    self.backtracking(n, k, 0, 1, [], result)
    return result
  • 这个方法是整个问题的入口。它接受两个参数,k表示需要找到的数字个数,n表示这些数字的和。
  • result是一个空列表,用来存储最终满足条件的所有组合。
  • self.backtracking(n, k, 0, 1, [], result)调用了一个递归函数backtracking,这个函数是实现回溯的核心部分。
def backtracking(self, targetSum, k, currentSum, startIndex, path, result):
    if currentSum > targetSum:  # 剪枝操作
        return  # 如果path的长度等于k但currentSum不等于targetSum,则直接返回
    if len(path) == k:
        if currentSum == targetSum:
            result.append(path[:])
        return
    for i in range(startIndex, 9 - (k - len(path)) + 2):  # 剪枝
        currentSum += i  # 处理
        path.append(i)  # 处理
        self.backtracking(targetSum, k, currentSum, i + 1, path, result)  # 注意i+1调整startIndex
        currentSum -= i  # 回溯
        path.pop()  # 回溯
  • 剪枝操作

    • if currentSum > targetSum::如果当前组合的和已经超过了目标和,则没有必要继续向下探索,直接返回。

    • if len(path) == k::当组合中的数字个数已经达到k,如果组合的和正好等于targetSum,则将该组合加入结果集。否则直接返回。

  • 循环结构

    • for i in range(startIndex, 9 - (k - len(path)) + 2)::这个循环用于从当前的startIndex开始,逐个选择数字来构造组合。这里的9 - (k - len(path)) + 2是一个剪枝优化,确保剩余的数字数量足够填满path
  • 递归与回溯

    • currentSum += ipath.append(i):将当前选中的数字加入组合,并更新当前和。

    • self.backtracking(targetSum, k, currentSum, i + 1, path, result):递归调用backtracking方法,继续探索下一个数字。

    • currentSum -= ipath.pop():在递归返回后,进行回溯,将当前选中的数字移除,以便探索其他可能的组合。

  • 11
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值