Given a set of candidate numbers (C) (without duplicates) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.
The same repeated number may be chosen from C unlimited number of times.
Example 1:
given candidate set [2, 3, 6, 7] and target 7.
solution is [[7], [2, 2, 3]].
这道题其实是考回溯,我习惯了用递归去做,整个过程当成了是一个深度搜索。枚举每一个元素作为根节点,然后每一个递归就添加一个新的节点,如果路径上的节点之和等于target就得到了一组结果,如果路径和大于target表示可以结束当前的搜索,返回上一层,尝试以下一个元素作为新节点的路径。最后返回得到的所有结果,需要注意的地方是递归结束返回后,需要把添加的节点去除,所以我的代码里在递归调用语句的前后分别有push_back跟pop_back。理解了算法的思想,整个过程其实很直观。
大神们的解法基本都是常规的回溯,当然,他们的实现始终比我要简洁,下面给出了他们的代码进行参考。
class Solution {
public:
void dfs(vector<vector<int>> &res, vector<int>& c, vector<int> comb, int t, int sum, int cur) {
for (int i = cur; i < c.size(); i++) {
sum += c[i];
comb.push_back(c[i]);
if (sum == t) {
res.push_back(comb);
return ;
} else if (sum > t) {
return;
}
dfs(res, c, comb, t, sum, i);
sum -= c[i];
comb.pop_back();
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
vector<vector<int>> res;
vector<int> comb;
sort(candidates.begin(), candidates.end());
dfs(res, candidates, comb, target, 0, 0);
return res;
}
};
class Solution {
public:
vector<vector<int> > combinationSum(vector<int> &candidates, int target) {
sort(candidates.begin(), candidates.end());
vector<vector<int> > res;
vector<int> comb;
combinationSum(candidates, target, res, comb, 0);
return res;
}
private:
void combinationSum(vector<int> &cand, int target, vector<vector<int>> &res, vector<int> &comb, int begin) {
if (!target) {
res.push_back(comb);
return;
}
for (int i = begin; i != cand.size() && target >= cand[i]; ++i) {
comb.push_back(cand[i]);
combinationSum(cand, target - cand[i], res, comb, i);
comb.pop_back();
}
}
};
类似这种题目的问题有很多,一般都是把结果当作是叶子节点,中间状态作为中间节点,根据深搜的过程一边构建树一边求解,这只是我自己理解的一种方法,而经典的回溯问题还有N皇后问题,可以见我的这篇博客LeetCode 52. N-Queens II 解题报告。
接下来两周都有考试,得认真复习了,然后到了7月份就得去网易游戏实习,未曾实习过的我开始觉得紧张了,趁还有时间要多准备准备,加油!