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]]
解题思路:
保存一个目标对象数组,这里是1-9,然后使用回溯的方法求所有可能相加的结果。
代码实现如下:
class Solution {
private:
vector<vector<int>> result;
vector<int> nums;
public:
vector<vector<int>> combinationSum3(int k, int n) {
vector<int> mid_rlt;
nums = vector<int>(9);
for(int i = 1; i < 10; ++i)
nums[i-1] = i;
backtracking(mid_rlt, n, 0, k);
return result;
}
void backtracking(vector<int> mid_rlt, int remain, int index, int count) {
if(remain == 0 && count == 0) {
result.push_back(mid_rlt);
return;
}
for(int i = index; nums[i] <= remain && i < 9; ++i) {
mid_rlt.push_back(nums[i]);
backtracking(mid_rlt, remain - nums[i], i+1, count-1);
mid_rlt.pop_back();
}
}
};
在上述基础上我们还可以进行剪枝。给定一个数字以及要求组成他的数字的个数,我们能够判断这些数字的个数能够组成的最大值和最小值。因此在回溯之前加上这样一个判断可以大大提高效率。
代码如下:
class Solution {
private:
vector<vector<int>> result;
vector<int> nums;
public:
vector<vector<int>> combinationSum3(int k, int n) {
vector<int> mid_rlt;
nums = vector<int>(9);
for(int i = 1; i < 10; ++i)
nums[i-1] = i;
backtracking(mid_rlt, n, 0, k);
return result;
}
void backtracking(vector<int> mid_rlt, int remain, int index, int count) {
if(getMin(count) > remain || getMax(count) < remain)
return;
if(count == 0) {
if(remain == 0)
result.push_back(mid_rlt);
return;
}
for(int i = index; nums[i] <= remain && i < 9; ++i) {
mid_rlt.push_back(nums[i]);
backtracking(mid_rlt, remain - nums[i], i+1, count-1);
mid_rlt.pop_back();
}
}
int getMin(int k) {
int minValue(0);
for(int i = 0; i < k; ++i)
minValue += nums[i];
return minValue;
}
int getMax(int k) {
int maxValue(0);
for(int i = 0; i < k; ++i)
maxValue += nums[8-i];
return maxValue;
}
};