题目:

思路:
K神的思路清晰明了,推荐阅读:
https://leetcode.cn/problems/combination-sum/solutions/2363929/39-zu-he-zong-he-hui-su-qing-xi-tu-jie-b-9zx7/?envType=study-plan-v2&envId=top-100-liked
https://leetcode.cn/problems/combination-sum/solutions/2363929/39-zu-he-zong-he-hui-su-qing-xi-tu-jie-b-9zx7/?envType=study-plan-v2&envId=top-100-liked跟全排列的做法差不多,但是需要两次剪枝:一是和不能超过目标值;二是去重[3,4]和[4,3]是一样的
代码:
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
def backtrack(
state: list[int], target: int, choices: list[int], start: int, res: list[list[int]]
):
if target == 0:
res.append(list(state))
return
for i in range(start,len(choices)):#从start开始,能去重
if target - choices[i] < 0:#结果不能大于target
break
state.append(choices[i])
backtrack(state,target-choices[i],choices,i,res)#因为可以重复选,所以这里的start是i而不是i+1
state.pop()
state = []
candidates.sort()#在遍历所有选择时,当子集和超过 target 时直接结束循环,因为后边的元素更大,其子集和都一定会超过 target 。
start = 0
res = []
backtrack(state,target,candidates,start,res)
return res