题目:
题目链接: https://leetcode-cn.com/problems/combination-sum/
解题思路:
"所有组合"字样,考虑递归回溯 + 剪枝的思路
递归前先对数组进行排序,递归函数的设计如下:
def __search(self, candidates, start, end, path, res, target):
参数说明:
candidates : 排序后的原始数组
start : 当前递归层数中的首个元素下标
end : 原始数组元素个数
path : 当前搜索的数字路径
res : 符合条件的结果集合
target : 当前递归的目标值
递归函数的思路如下:
- 对入口的目标值进行判断,如果为0,则保存当前路径的数字组合,并返回
- 如果不为0,进行下记循环
- 获取当前循环的数字(index in range(start, end)),并计算需要寻找的下个目标值next_target = target - [index]
- 如果next_target < 0,因为数组已排序,后面的元素只会导致next_target越来越小,所以为了提升效率,此时直接退出,无需继续遍历(剪枝)
- 如果next_target >= 0,递归调用自己,各参数更新为:
- start = index
- path = path.append([index])
- target = next_target
- 继续循环,直到遍历完所有元素,或者满足2.2中的退出条件
尝试着画了几次图,都没有leetcode题解中的下面这张图好,就直接拿来用了=,=
出处是leetcode题解中最高赞的liweiwei1419写的题解
代码实现:
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
num_len = len(candidates)
if num_len == 0:
return []
candidates.sort()
res, path = [], []
self.__search(candidates, 0, num_len, path, res, target)
return res
def __search(self, candidates, start, end, path, res, target):
if target == 0:
res.append(path[:])
return
for index in range(start, end):
next_target = target - candidates[index]
if next_target < 0:
break
path.append(candidates[index])
self.__search(candidates, index, end, path, res, next_target)
path.pop()