Leetcode 216.组合总和III

1.题目描述

找出所有相加之和为 n 的 k 个数的组合,且满足下列条件:

  • 只使用数字1到9
  • 每个数字 最多使用一次
    返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。

示例:

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

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

2.思路分析

相对于77. 组合,无非就是多了一个限制,本题是要找到和为n的k个数的组合,而整个集合已经是固定的了[1,…,9]。

  • k:相当于树的深度
  • 9:相当于树的宽度

例如: k = 2,n = 4的话,就是在集合[1,2,3,4,5,6,7,8,9]中求 k(个数) = 2, n(和) = 4的组合。
在这里插入图片描述

从图中可以看出符合条件的组合为:(1,3)

回溯三部曲:

  • 确定回溯函数的参数以及返回值

    # 存放结果集
    result = []
    # 存放符合条件的结果
    path = []
    
    • targetSum:目标和(对应题目中的n)
    • k:集合元素的个数
    • sum:已收集元素的总和(path中的元素和)
    • startIndex:控制循环的起始位置
    result = []
    path = []
    def backtracking(targetSum:int, k:int, sum:int, startIndex:int)->None:
    
  • 确定终止条件

    path.size == k 就终止了

    如果path中的元素和 == targetSum,result收集结果

     if len(path) == k:  # len(path)==k时不管sum是否等于n都会返回
                if path_sum== n:
                    res.append(path[:])
                return
    
  • 确定单层搜索逻辑

在这里插入图片描述

3.剪枝优化

在这里插入图片描述

 if path_sum > n:  
            return

4.代码实现

class Solution:
    def combinationSum3(self, k: int, n: int) -> List[List[int]]:
        # 定义全局变量
        result, path = [], []

        def backtrack(k: int, targetSum: int, path_sum: int, startIndex: int) -> None:
            # 剪枝操作
            if path_sum > targetSum:
                return 
            # 终止条件
            if len(path) == k:
                if path_sum == targetSum:
                    result.append(path[:])
                return
            # 单层搜索逻辑
            # for i in range(startIndex, 10):[1,...,9]
            # 已选择的元素个数:len(path)
            # 需要的元素个数:k-len(path)
            # 在集合n中至多要从该起始位置 : n - (k - path.size()) + 1,开始遍历
            for i in range(startIndex, 10 - (k - len(path)) + 1):
                # 处理节点
                path.append(i)
                path_sum += i
                # 递归
                backtrack(k, targetSum, path_sum, i + 1)
                # 回溯
                path.pop()
                path_sum -= i

        backtrack(k, n, 0, 1)
        return result

注:

result.append(path)产生错误的结果,而result.append(path[:])会产生正确的结果

区别:

result.append(path) : 将path这个列表地址添加到result中,因此当后面path改变时,result中的path会不断发生改变,并不会保存当时想要得到的结果

result.append(path[:])是将path列表中存储的值复制到一个新的地址中去,result是添加新的地址的值,因此后面无论path的值如何改变,都不会影响这个添加进去的值,因此在通常保存列表结果时,应该使用path[:]

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值