题目大意:将k个不同的数字相加,使得所求的和为n,要求这些数字只能从1到9中间取,并且不能重复。求出所有满足的情况,并且按从小到的顺序排列后存入列表。例如:k=3,n=7,结果应为:[[1,2,4]]。再比如:k = 3, n = 9,结果为:[[1,2,6], [1,3,5], [2,3,4]]。
解题思路:此题很显然要用递归。递归返回(存入列表)的条件为:选得的数字个数等于k,并且sum等于n。要选的第一个数字(序列中最小值)从1到9进行遍历,先选1可以吗?接着先选2?……一直到9。
具体做法:实现一个帮助函数combinationSum3Helper(int k, int sum, int n, int i, vector<int>& tmp, vector<vector<int> >& result)。
每次新调用一个帮助函数k都减1,一直减到0说明要求的k个数字名额满了。
sum存储当前所得的和,等于n时说明满足。
i表示可选的数字为i到9。
result存储最终结果。
tmp用来存储已经选得的数字,如果最终满足了条件sum == n && k == 0,就能把tmp存入result。注意tmp的回溯,每一个帮助函数返回时都会有一次pop_back()。
代码如下:
1 class Solution { 2 public: 3 vector<vector<int>> combinationSum3(int k, int n) { 4 vector<int> tmp; 5 vector<vector<int> > result; 6 combinationSum3Helper(k, 0, n, 1, tmp, result); 7 return result; 8 } 9 void combinationSum3Helper(int k, int sum, int n, int i, vector<int>& tmp, vector<vector<int> >& result) 10 { 11 if(sum == n && k == 0) 12 { 13 result.push_back(tmp); 14 return; 15 } 16 else if(sum > n || k <= 0) return; 17 18 for(int j = i; j <= 9; ++j)//从i到9中间选数字 19 { 20 tmp.push_back(j); 21 combinationSum3Helper(k-1, sum+j, n, j+1, tmp, result);//如果说该句结束了,要么是当前元素不可能满足,要么是已经写入了result 22 tmp.pop_back();//保证了每次写入result以后清空当前的tmp,或者不可能满足的情况下清空当前的tmp 23 } 24 } 25 };