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;
}
};