39. 组合总和
给定一个无重复元素的数组
candidates
和一个目标数target
,找出candidates
中所有可以使数字和为target
的组合。
candidates
中的数字可以无限制重复被选取。说明:
- 所有数字(包括
target
)都是正整数。- 解集不能包含重复的组合。
示例 1:
输入: candidates = [2,3,6,7], target = 7, 所求解集为: [ [7], [2,2,3] ]
示例 2:
输入: candidates = [2,3,5], target = 8, 所求解集为: [ [2,2,2,2], [2,3,3], [3,5] ]
解法一:
//时间复杂度O(?), 空间复杂度O(?)
class Solution {
public:
void DFS(vector<int>& candidates, int target, vector<vector<int>>& res, vector<int>& cur) {
if(target < 0) return;
if(target == 0) {
res.push_back(cur);
return;
}
for(int elem : candidates) {
if(!cur.empty() && elem > cur[cur.size() - 1]) continue;
cur.push_back(elem);
DFS(candidates, target - elem, res, cur);
cur.pop_back();
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
sort(candidates.begin(), candidates.end());
vector<vector<int>> res;
vector<int> cur;
DFS(candidates, target, res, cur);
return res;
}
};
思路:
最初的解法实现了全组合,遍历每一种情况,不出意外地超时了。
另一种解法是回溯的思想,从target出发探索每一种可能。以下思路参考了题解。
以7为根构建一棵树,除叶子结点外,每个结点都有candidates.size()个子结点,子结点值为父结点值 - candidates[i](0 <= i < candidates.size())。叶子结点的值都不大于0。
该树的每一个从根到值为0的叶结点的路径中,父子结点的差所组成的cur数组就是所求的组合。
为了去重,需要事先对candidates按升序排序,去除非升序的cur数组,其余的都是不重复的解。
2019/09/27 23:36