组合总和 回溯与递归

给定一个无重复元素的正整数数组 candidates 和一个正整数 target ,找出 candidates 中所有可以使数字和为目标数 target 的唯一组合。

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

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

示例 1

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

输出: [[7],[2,2,3]]

示例 2

输入: candidates = [2,3,5], target = 8

输出: [[2,2,2,2],[2,3,3],[3,5]]

示例 3

输入: candidates = [2], target = 1

输出: []

示例 4

输入: candidates = [1], target = 1

输出: [[1]]

示例 5

输入: candidates = [1], target = 2

输出: [[1,1]]

思路:

  数字可以重复使用,就相当于有放回地取数字。那我们同样可以想象“一棵选择树”,假如有选择列表[2,3,5],我们第一个数有三个选择,对于不同的选择,我们又可以分别进行三个分支。从一个状态如何分别去体验三个分支呢?——之前的题目中讲过,就用回溯+递归

  因为题目中提到有唯一组合,所以一旦等于target,要对数组排序来判重——因为[2,2,3][2,3,2]其实是一样的;若当前加和大于target,直接返回结束。

    回溯的方法很简单,主要就是两个参数(haschoosehas是现有的状态,choose是选择列表。要注意的是,每进行一个选择后,要马上退回原状态,方便进入下一个选择。

代码:

class Solution(object):

    def combinationSum(self, candidates, target):

        #用回溯!!!!!!!!!!!

        def hui(has,choose,target):

            if sum(has)==target:#满足条件

                if sorted(has) not in res:#看看排序后的数组是否已存在

                    res.append(sorted(has))#不存在就放进结果

            elif sum(has)>target:#加和超过target了,直接返回,放弃

                return

            for c in choose:#回溯加递归

                has.append(c)#添加进新的选择

                hui(has,choose,target)#送入递归

                has.pop(-1)#撤回选择

        res = []#存放结果的列表

        hui([],candidates,target)#当前has为空,choose选择列表为candidates

        return res

小结:

  这道题是练习回溯的经典题目,而回溯记住主要的思路和框架就好了。

  这里回溯函数还写了第三个参数target,也完全可以拿出来当全局变量。这个不影响,回溯的精髓还是has和choose两个参数。如果把target的当作全局变量的话,单纯地写在函数外面好像是不可以的,leetcode有可能报找不到变量的错。有个小技巧是把target写成列表(包含一个元素的列表),即用列表来充当全局变量。如在函数外面定义target=[target]即可。

posted @   JunanP  阅读(5)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示