组合总和 回溯与递归
给定一个无重复元素的正整数数组 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,直接返回结束。
回溯的方法很简单,主要就是两个参数(has,choose),has是现有的状态,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]即可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了