回溯算法(4) 继续练习题目

给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。

candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。 

对于给定的输入,保证和为 target 的不同组合数少于 150 个。

输入:candidates = [2,3,6,7], target = 7
输出:[[2,2,3],[7]]

可以看出 元素是可以重复选的 那么return 条件就是相加等于target 就存储到列表数组中 但是结果是顺序无关的 那么就是组合 

我们来先试着写一下代码

class Solution(object):
    def combinationSum(self, candidates, target):
        res = []
        def backtrack(path):
            if sum(path) == target:  # 检查当前路径的和
                res.append(path.copy())  # 记录合法组合
                return
            #剪枝条件就是只有和小于target的时候 才可以继续往下
            if sum(path)<target:
                for i in candidates:
                    path.append(i)
                    backtrack(path)
                    path.pop()#回溯
        backtrack([])
        return res
solution=Solution()
result=solution.combinationSum([2,3,6,7],7)
print(result)

这个是我第一遍写的代码 我的思路很简单 就是在path之和等于target的时候return 要想继续进行下去 path之和必须小于target才行 如果小于 那么就在这个candidates中选择 因为可以重复选择 将i加上去 然后递归 如果等于那么就return  之后将这个加上去的元素pop 尝试其他新的元素 如果不小于 那这个枝条就被剪掉了 如果小于 就继续执行 (建议是将最简单的全排列看懂 其他的就按照这个模式来写 不然会觉得心里乱糟糟的)

然后输出结果是这样的:[[2, 2, 3], [2, 3, 2], [3, 2, 2], [7]]

很明显 重复了 因为要按照一个组合来看 而不是一个排列 排列的话顺序不同也会是不同的结果 但是组合的话是不管顺序的

class Solution(object):
    def combinationSum(self, candidates, target):
        res = []
        def backtrack(start,path):
            if sum(path) == target:  # 检查当前路径的和
                res.append(path.copy())  # 记录合法组合
                return
            #剪枝条件就是只有和小于target的时候 才可以继续往下
            if sum(path)<target:
                for i in range(start,len(candidates)):#start从0开始
                    path.append(candidates[i])
                    backtrack(i+1,path)#我这个代码的意思就是不能重复选或者回去选 就直接是i+1 这样的结果就会导致不符合题目的可以选择重复元素
                    path.pop()#回溯
        backtrack(0,[])
        return res
solution=Solution()
result=solution.combinationSum([2,3,6,7],7)
print(result)

看一下我这个代码的修改 这个代码的意思就是不会重复选 也不会再回头选 这样就会导致结果里面是没有重复的情况的 但是也会导致有些元素不能重复选 这个的打印结果是只有7这一个数组

但是我们想要的是不要回过去选 但是可以重复选 所以backtrack就可以使(i,path)这样就可以重复选择元素 传递 i(而不是 i+1)到下一层递归,使得​​当前元素 candidates[i] 可以被重复选择​​。 外层的 for i in range(start, len(candidates)) 保证了​​只会从 start 开始向后选​​,不会扫描 candidates[0..start-1] 的元素,因此​​不会回头选​​。

每次循环 i 从 start 递增,确保:

  1. ​同一层递归​​:尝试选择 candidates[start]candidates[start+1], ...
  2. ​下一层递归​​:通过 backtrack(i, path) 决定是否重复选当前元素或推进到下一个。
  3. 避免重复组合​​:
    即使允许重复选 ifor 循环的逐步推进仍会保证 [2,3] 和 [3,2] 不会同时出现(因为 3 不会回到 2

就是肯定会有些晕 但是我觉得也没必要太纠结 就按照逻辑走就行

如果你喜欢这篇文章 欢迎点赞收藏~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值