递归的思想:每一次的递归功能,我给它抽象为新找一个位,在该位上,这个数是可以变大的,以此来帮助sum变大从而匹敌 target。
这里有意思的地方在于每次都可以用原来的数。
(盗图~)
#include<iostream>
#include<vector>
using namespace std;
class Solution {
public:
vector<vector<int>> combinationSum(vector<int> candidates, int target) {
if(candidates.size() < 0)
return {};
sort(candidates.begin(), candidates.end());
if(target < candidates[0])
return {};
vector<vector<int> > result;
vector<int> temp;
int sum = 0;
getBacking(result, temp, candidates, sum, 0, target);
return result;
}
bool getBacking(vector<vector<int> >& result,vector<int>& temp, vector<int> nums, int sum, int k, int target){
// 若当前累计的数已经 比 target还要大了,我就 不额外再找一个数进行累加了
if(sum > target){
return false;
}else if(sum == target){
//如果外界让我再找一个数累加,但是我发现当前的值就已经足够了,不必再累加了,那么,我们就找到了答案
result.push_back(temp);
//因为当找到答案后,再累加也没有,所以干脆告诉上级,活干完了,你换下一个人吧。
return false;
}else{
for(int i=k;i<nums.size();i++){
//能到这里意味着当前的累计和sum比target值还小,还需要一个数值累加,而我们能让它类加的量为:nums【i】 --- nums[size-1]
temp.push_back(nums[i]);
sum += nums[i];
//ok,我加入了这个数了,但是,在让该位上的数循环变成更大一点的数前,我们看看是否还需要再加一个数,让这个数帮忙让sum更大一些。
bool flag = getBacking(result, temp, nums, sum, i, target);
// 不管我是否需要加入新的位 来帮忙增大sum,此刻,本身所在位的数值是必须要增大的
temp.pop_back();
//记得扣除
sum -= nums[i];
if(!flag){
//如果我们的孩子告诉我们,娘亲啊,你现在在这个位置加上的数就已经让sum超过了target,不能再让该位的值增大了,不然大清就亡了。
//so,我们要退出这个for,
//次外,如果当前为的值被加上后刚好等于目标,我们也不用继续在把该位上的值增加了,因为值只会越来越大。
break;
}
//如果没退出,那就把该位上的值增大
}
//对上层调用的函数而言,新加位的所有可能都已经试过了,所以要返回,并且让上一层所在的数值增大
return true;
}
}
};
int main(){
Solution s;
vector<int> can(1,1);
s.combinationSum(can,1);
return 0;
}