39题,翻译题目:
给定一组候选集(C)和一个目标值T,在C的所有组合中,找出所有总和等于T的组合。
候选数组C中同一个数可以被选择多次(不限次数)。解集不能包含重复的组合。
[ 2,2,3 ]
分析:
典型的回溯法应用。
对数组里面的每个数,用递归的方式相加,每次递归将和sum与target作比较,若相等则加入结果vector,sum>target则舍弃,并返回false,若sum
第一种sum=target的情况下,在加入结果vector后回溯(此时不应再累加),要将当前一种结果最后加入的元素pop_back(),并继续对后面的元素进行递归;
第二种sum>target的情况下,则需要将当前结果的最后加入的元素pop_back(),并继续对后面的元素进行递归。
第三种sum
注意元素可以重复,所以下一次递归总是从当前递归元素开始。
class Solution {
public:
void dfs(vector& nums, vector &subres,int sum, int start, int target)//使用引用,有利于防止内存大爆炸
{
if(sum == target)//已经获得答案,并且回溯
{
result.push_back(subres);
return;
}
for (int i = start; i < nsize; i++)
{
if(nums[i] > target || (sum+nums[i]) > target)//这条路不符要求,回溯
return;
subres.push_back(nums[i]);
dfs(nums, subres,sum+nums[i],i,target);//执行一个深度上的组合,并计算和。
subres.pop_back();//每当执行完一个深度上的组合就弹掉末尾元素
}
}
vector> combinationSum(vector& candidates, int target) {
nsize=candidates.size();
if ( nsize == 0)
return result;
sort(candidates.begin(),candidates.end()); //一,先排序
vector subres;
dfs(candidates, subres,0,0, target);
return result;
}
private:
vector > result;
int nsize;
};
40题,翻译题目:
给定一组候选集(C)和一个目标值T,在C的所有组合中,找出所有总和等于T的组合。
候选数组C中每个数字只能使用一次。
分析:
典型的回溯法应用。
这道题跟上一道题基本一模一样,唯一区别就是每个数只能用一次,因此代码上只需要改一点点就行,即下一层递归
不能再从当前数开始,而要从下一个数开始了
class Solution {
public:
vector > combinationSum2(vector &num, int target)
{
sort(num.begin(),num.end());
vector subresult;
dfs( 0, target, subresult, num);
return result;
}
void dfs(const int order, const int target, vector& subresult, const vector& num)
{
if(target==0)
{
result.push_back(subresult);
return;
}
for(int i = order;itarget)
return;
if(i&&num[i]==num[i-1] && i>order)
continue; // check duplicate combination
subresult.push_back(num[i]),
dfs(i+1,target-num[i],subresult,num); // recursive componenet
subresult.pop_back();
}
}
private:
vector > result;
};
41题,题目:
Find all possible combinations of k numbers that add up to a number n, given that only numbers
from 1 to 9 can be used and each combination should be a unique set of numbers.
Ensure that numbers within the set are sorted in ascending order.
Example 1:
Input: k = 3, n = 7
Output:
[[1,2,4]]
Example 2:
Input: k = 3, n = 9
Output:
[[1,2,6], [1,3,5], [2,3,4]]
分析:
这道题是组合之和系列的第三道题,跟之前两道Combination Sum 组合之和,Combination Sum II 组合之和联系比较紧密,变化不大,而这道跟它们最显著的不同就是这道题的个数是固定的,为k。个人认为这道题跟那道Combinations 组合项更相似一些,但是那道题只是排序,对k个数字之和又没有要求。所以实际上这道题是它们的综合体,两者杂糅到一起就是这道题的解法了,n是k个数字之和,如果n小于0,则直接返回,如果n正好等于0,而且此时out中数字的个数正好为k,说明此时是一个正确解,将其存入结果res中,具体实现参见代码入下:
class Solution {
public:
void dfs(vector &subres,int curSum,int start, int target)//使用引用,有利于防止内存大爆炸
{
if (subres.size()==nsize && curSum == target)//显然此时要满足两个条件才能获得答案,并且回溯
{
result.push_back(subres);
return;
}
for (int i = start; i <= 9; i++)
{
if(i > target || (curSum+i) > target)//此种情况即可回溯
return;
subres.push_back(i);
dfs(subres,curSum+i,i + 1,target);//执行一个深度上的组合,并计算和。计算和时一定要这样计算(可以保留本层的sum)
subres.pop_back(); //每当执行完一个深度上的组合就弹掉末尾元素 ,准备下一轮回溯寻找组合
}
}
vector> combinationSum3(int k, int n) {
if ( k == 0)
return result;
nsize=k;
vector subres;
dfs(subres,0,1,n);
return result;
}
private:
vector > result;
int nsize;
};
注:本博文为EbowTang原创,后续可能继续更新本文。如果转载,请务必复制本条信息!
原文地址:http://blog.csdn.net/ebowtang/article/details/50853069
原作者博客:http://blog.csdn.net/ebowtang
本博客LeetCode题解索引:http://blog.csdn.net/ebowtang/article/details/50668895