emmm,最近在刷题,可是我发现,我只要碰到递归和回溯都会有思路,可我就是不会写代码,因为代码实际考虑的东西很多,每次看完题解之后就会写了,但是其实我感觉我还是不太会,所以,我决定适当的记录一下,慢慢培养我的思路。嘻嘻,从今天开始,我会自主出发去考虑解法,把回溯、递归、动态规划拿在手中,变成一个无所不能的大佬,从此一统天下。。。(我靠,停止做梦!)
进入正题,今天,这道题来自力扣39题,组合总和:
给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的数字可以无限制重复被选取。
说明:
所有数字(包括 target)都是正整数。
解集不能包含重复的组合。
示例 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]
]
看到题目,我就能想象出一颗树:
对于图片的描述:
1.打叉的代表不进行选择,就是数组中这个数比target大的时候不选择。
2.当target==0的时候,收入结果数组
之后就是代码书写,考虑几个问题:
1.怎么记录:利用数组k和数组result进行记录,数组k记录每次深度选择,当target==0的时候加入result数组,每次进行深度选择的时候就是新的一次递归调用,因此把k和result作为参数传递,([2]->[2,2]->[2,2,2]),还有一个问题,怎么回到同一层,每次一个for 就是一个同级选择,因此在递归后,就pop掉进行下一个同级选择即可。
2.注意去掉重复选项,只要保证下一个选择不必上一个选择小即可。
代码:
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
def back(begin,lists,target,k,result):
if(target==0):
result.append(k[:])# Python 中可变对象是引用传递,因此需要将当前 path 里的值拷贝出来
for i in range(begin,len(lists)):# begin的设计是为了防止重复
if(lists[i]<=target):
k.append(lists[i])
back(i,lists,target-lists[i],k,result)
k.pop()# 深度优先到同级
candidates=sorted(candidates)
result=[]
k=[]
back(0,candidates,target,k,result)
return result