0
点赞
收藏
分享

微信扫一扫

LeetCode 组合总和


文章目录

  • ​​39 组合总和​​
  • ​​40 组合总和II​​
  • ​​216 组合总和 III​​

39 组合总和

LeetCode 组合总和_c++

当前sum大于target时,就停止进入解空间树下一层

LeetCode 组合总和_算法_02

class Solution {
public:
vector<vector<int>> ans;
vector<int> arr;
int cur_sum;

void func(int start, const vector<int>& candidates, const int target){
if(cur_sum > target){
return;
}
if(cur_sum == target){
ans.push_back(arr);
return;
}
for(int i = start; i < candidates.size(); i++){
arr.push_back(candidates[i]);
cur_sum += candidates[i];
func(i, candidates, target);
cur_sum -= candidates[i];
arr.pop_back();
}
}

vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
cur_sum = 0;
func(0, candidates, target);
return ans;
}
};

剪枝: 将candidates进行排序,当前sum加上下一个元素大于target时,就不进入解空间树下一层

LeetCode 组合总和_c++_03

class Solution {
public:
vector<vector<int>> ans;
vector<int> arr;
int cur_sum;

void func(int start, const vector<int>& candidates, const int target){
if(cur_sum == target){
ans.push_back(arr);
return;
}
for(int i = start; i < candidates.size() && cur_sum + candidates[i] <= target; i++){
arr.push_back(candidates[i]);
cur_sum += candidates[i];
func(i, candidates, target);
cur_sum -= candidates[i];
arr.pop_back();
}
}

vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
sort(candidates.begin(), candidates.end());
cur_sum = 0;
func(0, candidates, target);
return ans;
}
};

40 组合总和II

LeetCode 组合总和_i++_04

LeetCode 组合总和_算法_05

由于给定的candidates存在重复元素,还按照​​39 组合总和​​中的算法就会发生上述组合重复的情况,可以看到红框的两个部分完全一样,即不应该生成第二个红框中的节点。同一层节点不允许有重复,如果重复则不应该往下继续生成节点

LeetCode 组合总和_c++_06


根据used数组判断是同一树层重复了,还是往下深入时使用了重复的元素,同一数层不允许重复使用元素,但是往下深入时可以使用重复元素

  • used[i - 1] == true,说明同一树枝candidates[i - 1]使用过,可以选择
  • used[i - 1] == false,说明同一树层candidates[i - 1]使用过,则应该挑选下一个元素,continue

class Solution {
public:
vector<vector<int>> ans;
vector<int> arr;
vector<bool> used;
int cur_sum;

void func(int start, const vector<int>& candidates, const int target){
if(cur_sum == target){
ans.push_back(arr);
return;
}
for(int i = start; i < candidates.size(); i++){
if(i > 0 && candidates[i] == candidates[i-1] && used[i - 1] == false){
continue;
}
if(cur_sum + candidates[i] > target){
break;
}
arr.push_back(candidates[i]);
cur_sum += candidates[i];
used[i] = true;
func(i + 1, candidates, target);
used[i] = false;
cur_sum -= candidates[i];
arr.pop_back();
}
}

vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
sort(candidates.begin(), candidates.end());
cur_sum = 0;
used.resize(candidates.size(), false);
func(0, candidates, target);
return ans;
}
};

216 组合总和 III

LeetCode 组合总和_i++_07

为避免数字重复或组合重复,升序取数字即可,解空间树如下图所示:

LeetCode 组合总和_算法_08

根据解空间树翻译出代码:

class Solution {
public:
int cur_sum = 0;
vector<vector<int>> ans;
vector<int> arr;

void func(int i, int start, int k, int n){
if(i == k){
if(cur_sum == n){
ans.push_back(arr);
}
return;
}
// 这里不能是i+1,而应该是start
for(int j = start; j <= 9; j++){
if(cur_sum + j > n){
// 和大于n了,就不再往arr中放数据了,退出for循环,回溯到上一层
break;
}
arr.push_back(j);
cur_sum += j;
func(i + 1, j + 1, k , n);
cur_sum -= j;
arr.pop_back();
}
}

vector<vector<int>> combinationSum3(int k, int n) {
func(0, 1, k, n);
return ans;
}
};

剪枝方法同​​LeetCode 77. 组合​​,最终的目的就是:当前剩余能挑选的元素数量能够满足还需要的元素数量

class Solution {
public:
int cur_sum = 0;
vector<vector<int>> ans;
vector<int> arr;

void func(int i, int start, int k, int n){
if(i == k){
if(cur_sum == n){
ans.push_back(arr);
}
return;
}
// 这里不能是i+1
for(int j = start; j <= 9 - (k - arr.size()) + 1; j++){
if(cur_sum + j > n){
break;
}
arr.push_back(j);
cur_sum += j;
func(i + 1, j + 1, k , n);
cur_sum -= j;
arr.pop_back();
}
}

vector<vector<int>> combinationSum3(int k, int n) {
func(0, 1, k, n);
return ans;
}
};


举报

相关推荐

0 条评论