刷题思路笔记,加油!
给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的数字可以无限制重复被选取。
递归实现回溯法的深度优先搜索策略,带重复项的排列树,复杂度O(n!)
改进:先对 candidates.sort()排序,定义剪枝函数。
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
res = []
candidates.sort()
self.dfs(candidates, target, 0, [], res)
return res
def dfs(self, nums, target, index, path, res):
if target == 0:
res.append(path)
return
if path and target < path[-1]: #剪枝函数
return
for i in range(index, len(nums)):
self.dfs(nums, target-nums[i], i, path+[nums[i]], res)
查看网上大佬解法,提到递归能解决的考虑迭代,这两者的区别如下:
迭代:利用变量的原值推算出变量的一个新值.如果递归是自己调用自己的话,迭代就是A不停的调用B.
递归中一定有迭代,但是迭代中不一定有递归,大部分可以相互转换.能用迭代的不用递归,递归调用函数,浪费空间,并且递归太深容易造成堆栈的溢出.
class Solution(object):
def combinationSum(self, candidates, target):
"""
:type candidates: List[int]
:type target: int
:rtype: List[List[int]]
"""
candidates = sorted(set(candidates))
result = list()
stack = [(0, list(), target)]
cand_len = len(candidates)
while stack:
i, path, remain = stack.pop()
while i < cand_len:
if path and remain < path[-1]:
break
if candidates[i] == remain:
result.append(path + [candidates[i]])
stack += [(i, path + [candidates[i]], remain - candidates[i])]
i+=1
return result