📜  组合总和(1)

📅  最后修改于: 2023-12-03 14:56:50.806000             🧑  作者: Mango

组合总和

组合总和是一道常见的算法题目,其目的是在给定的一组数中找到所有相加等于指定目标数的组合。这是一道经典的回溯算法问题,在算法竞赛和面试中都有出现。

算法描述

给定一个无重复元素的数组 candidates 和一个目标数 target,找出 candidates 中所有可以使数字和为 target 的组合。candidates 中的数字可以无限制地被选取。

说明:

  • 所有数字(包括 target)都是正整数。
  • 解集不能包含重复的组合。

示例:

输入:candidates = [2,3,6,7], target = 7, 输出:[[2,2,3],[7]]

解题思路

经典的回溯算法问题。每次从数组中选择一个元素,累加到当前结果中,再递归搜索剩下的元素,直到累加和等于 target 或者大于 target 为止。如果累加和等于 target,则将当前结果保存到答案中。如果累加和大于 target,则回溯,尝试选择下一个元素。

具体实现见下方代码片段。

代码实现
class Solution:
    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
        def backtrack(start_index, path, target):
            if target == 0:
                res.append(list(path))
                return
            for i in range(start_index, n):
                if candidates[i] <= target:
                    path.append(candidates[i])
                    backtrack(i, path, target - candidates[i])
                    path.pop()
        res = []
        candidates.sort()
        n = len(candidates)
        backtrack(0, [], target)
        return res
复杂度分析

时间复杂度:由于每个数可以重复使用多次,因此搜索深度至多为 target / min(candidates) 层。每层的时间复杂度为 O(n)。因此总时间复杂度为 O(n^(target/min)+1))。

空间复杂度:由于每个数字可以重复使用多次,因此递归树的宽度和高度都为 target/min(candidates)。因此空间复杂度为 O(target/min(candidates))。