标签:
如果还记的话或者写过LeetCode的人会知道,这是nsum,已经不再是之前的twosum,threesum,foursum了。之前是都是使用 i 层循环解题的,那么现在n层循环理论上是可以解题的(其实应该不行),但是n是不确定了,而且是可变的,其变化范围是[1,n]
说道这里其实想说明的是,我们要换种思路去解题了。我在看到这个题的时候想到的思路是:
我们从小到大一个一个将最小的数字重复不断的加入到 vector 中,若vector现有的值的和比 target 大则将 vector 集合中的元素减少一个,加入后面的元素继续比较,用到的还是回溯的方法。像这样递归加回溯最后肯定是可以求出所有的解的,其实这里还需要注意一点,就是判断vector中元素的和与target的大小关系时,我们不要直接将vector中所有元素的和求出来,而是利用一种巧妙的方法,将 ‘ target - val ‘ 作为 target 的更新值传递给循环(其中val指的是加入到vector中的值),最后target肯定会被减小到0的,此时真是我们要找到的值,将它加入到最终结果中。千万注意target不能以引用传递
上面的讲解可能会让你看的有些不懂,但是希望下面的代码能够帮助你理解,其实一旦思路明确后你就能解题了,代码如下:
class Solution { public: vector<vector<int>> combinationSum(vector<int>& candidates, int target) { /* 看到这个题的第一眼开始,我就想到了这个题和前面讲到的twosum,threesum,foursum不同,这个题目可能是 nsum, 所以n层循环的 做法不可取,我想到了是否可以回溯:不断加入元素,去测试,若元素的和与target相等则满足题意,若大于target则推出循环,若小于则 可以继续测试。 */ vector<vector<int>> ret; ret.clear(); vector<int> tmp; tmp.clear(); //题目并没有说明candidates是有序的,但是题目要求的结果是不能出现重复的集合,那么我们需要对candidates排序 sort(candidates.begin(),candidates.end()); //还是采用递归加上回溯法进行求解 _findAllSolve(candidates,ret,tmp,target,0); return ret; } void _findAllSolve(vector<int>& candidates, vector<vector<int>>& ret,vector<int>& tmp,int target, int index) { if(target == 0) {//此时说明tmp中的集合满足题意,加入到ret中 ret.push_back(tmp); return ; } else { for(int i = index; i < candidates.size(); ++i) { if(candidates[i] > target) {//题目中有说明candidates中元素都是非负的,而且candidates被排序过,此时可直接退出 return ; } //target > candidates[i] 那么我们就将candidates[i]加入到tmp中 tmp.push_back(candidates[i]); _findAllSolve(candidates,ret,tmp,target-candidates[i],i); //完成上面的过程后需要及时将它们移除,再看看还有其他的解没有 tmp.pop_back(); } } } };程序的结果如下:
标签:
原文地址:http://blog.csdn.net/zr1076311296/article/details/51374923