代码随想录算法训练营day22 | 77. 组合、216.组合总和III、17. 电话号码的字母组合
77.组合
解法一:不隐藏回溯
点击查看代码
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backtracking(int n, int k, int startIndex) {
if(path.size() == k) {
result.push_back(path);
return;
}
//剪枝:[i, n]区间中的元素个数要保证大于等于还需要的元素个数(不然把区间内所有元素都取了都不够
//n - i + 1 >= k - path.size()
for(int i = startIndex; i <= n - (k - path.size()) + 1; ++i) {
path.push_back(i);
backtracking(n, k, i + 1);
path.pop_back();
}
}
vector<vector<int>> combine(int n, int k) {
backtracking(n, k, 1);
return result;
}
};
解法二:隐藏回溯(由于要不断拷贝容器,导致时间空间复杂度均较高)
点击查看代码
class Solution {
public:
vector<vector<int>> result;
//vector<int> path;
vector<int> addNum(vector<int> v, int num) {
v.push_back(num);
return v;
}
void backtracking(int n, int k, int startIndex, vector<int> curPath) {
if(curPath.size() == k) {
result.push_back(curPath);
return;
}
//剪枝:[i, n]区间中的元素个数需保证大于等于缺的元素个数
//n - i + 1 >= k - path.size()
for(int i = startIndex; i <= n - (k - curPath.size()) + 1; ++i) {
backtracking(n, k, i + 1, addNum(curPath, i));
}
}
vector<vector<int>> combine(int n, int k) {
vector<int> path;
backtracking(n, k, 1, path);
return result;
}
};
216.组合总和III
点击查看代码
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backtracking(int &k, int &n, int curSum, int startIndex) {
if(curSum > n) return; //剪枝1
if(path.size() == k) {
if(curSum == n) result.push_back(path);
return;
}
for(int i = startIndex; i <= 9 - (k - path.size()) + 1; ++i) { //剪枝2
path.push_back(i);
backtracking(k, n, curSum + i, i + 1);
path.pop_back();
}
}
vector<vector<int>> combinationSum3(int k, int n) {
backtracking(k, n, 0, 1);
return result;
}
};
- 电话号码的字母组合
解法一:隐藏回溯
点击查看代码
class Solution {
public:
vector<string> numMap = {
"",
"",
"abc",
"def",
"ghi",
"jkl",
"mno",
"pqrs",
"tuv",
"wxyz"
};
//string path;
vector<string> result;
void backtracking(int index, string &digits, string path) {
if(index == digits.size()) {
result.push_back(path);
return;
}
string curSelectStr = numMap[digits[index] - '0'];
for(int i = 0; i < curSelectStr.size(); ++i) {
backtracking(index + 1, digits, path + curSelectStr[i]);
}
}
vector<string> letterCombinations(string digits) {
if(digits.size() == 0) return result; //无数字则直接返回空result
backtracking(0, digits, "");
return result;
}
};
解法二:显式回溯
由于各层函数共用全局容器path,并手动显式控制回溯过程,不会反复拷贝path容器,故空间复杂度更优
点击查看代码
class Solution {
public:
vector<string> numMap = {
"",
"",
"abc",
"def",
"ghi",
"jkl",
"mno",
"pqrs",
"tuv",
"wxyz"
};
string path;
vector<string> result;
void backtracking(int index, string &digits) {
if(index == digits.size()) {
result.push_back(path);
return;
}
string curSelectStr = numMap[digits[index] - '0'];
for(int i = 0; i < curSelectStr.size(); ++i) {
path.push_back(curSelectStr[i]); //处理
backtracking(index + 1, digits); //递归
path.pop_back(); //撤销处理,即回溯
}
}
vector<string> letterCombinations(string digits) {
if(digits.size() == 0) return result; //无数字则直接返回空result
backtracking(0, digits);
return result;
}
};

浙公网安备 33010602011771号