2023.6.27
这一题要求数组中的元素可以重复使用,但需要是不同的组合,例如[3,2,2]与[2,2,3]是同一个组合。这里与传统的组合问题的差异就在于,传统组合问题,在循环中进入递归时,startindex = i + 1(从当前遍历位置的下一个元素开始遍历)。如果元素可以重复使用,那就startindex = i(从当前遍历位置开始下一次遍历)。
非剪枝版:
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
self.result = [] # 保存最终结果
self.path = [] # 保存单次结果
self.target = target # 目标
self.candidates = candidates # 数组
self.n = len(candidates)
self.backtracking(0)
return self.result
def backtracking(self, startindex):
cursum = sum(self.path)
if cursum == self.target: # 终止条件
self.result.append(self.path[:])
return
elif cursum > self.target: # 剪枝
return
for i in range(startindex, self.n):
self.path.append(self.candidates[i])
self.backtracking(i)
self.path.pop()
剪枝版:
剪枝版的优势在于对数组进行升序排列后,当数组中一个元素添加到path中,cursum > target,则此元素后面的所有元素都大于此元素,也就没有必要继续遍历了。
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
self.result = [] # 保存最终结果
self.path = [] # 保存单次结果
self.target = target # 目标
self.candidates = candidates # 数组
self.candidates.sort()
self.n = len(candidates)
self.backtracking(0)
return self.result
def backtracking(self, startindex):
cursum = sum(self.path)
if cursum == self.target: # 终止条件
self.result.append(self.path[:])
return
for i in range(startindex, self.n):
if (cursum + self.candidates[i]) > self.target: # 剪枝
break
self.path.append(self.candidates[i])
self.backtracking(i)
self.path.pop()