Featured image of post Combination Sum

Combination Sum

39. 数组总和

分析

  • 使用深度优先搜索(DFS)+ 回溯的方法
  • 遍历候选数组 candidates 时,允许重复选择当前数字,目标值 target 减去选中的数字,直到达到目标(target == 0
  • target 不为 0,但已遍历完数组,表示当前路径无解,返回上一层
  • 回溯时移除已选择的数字

关键:每次递归时,既允许不选当前数字,也允许多次选取当前数字

时间复杂度

最坏情况下,candidates 长度为 n,每次递归中需要尝试所有可能的组合,时间复杂度为 O(2^n)

空间复杂度

递归深度为 target / min(candidates),路径存储需要 O(target / min(candidates))

C++代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Solution
{
public:
    std::vector<std::vector<int>> res;  // 存储结果集
    std::vector<int> path;             // 当前路径

    vector<vector<int>> combinationSum(vector<int>& candidates, int target)
    {
        dfs(candidates, 0, target);    // 从第一个数字开始递归
        return res;
    }

    void dfs(std::vector<int>& candidates, int u, int target)
    {
        if (target == 0)
        {             // 目标值为0,找到一种组合
            res.push_back(path);
            return;
        }
        if (u == candidates.size())    // 遍历完所有数字
            return;

        // 尝试选择当前数字若干次
        for (int i = 0; i * candidates[u] <= target; ++i)
        {
            dfs(candidates, u + 1, target - i * candidates[u]);  // 递归
            path.push_back(candidates[u]); // 将当前数字加入路径
        }
        for (int i = 0; i * candidates[u] <= target; ++i)
        {
            path.pop_back();           // 回溯,移除当前数字
        }
    }
};
Built with Hugo
Theme Stack designed by Jimmy