Day25回溯、组合总和
By HQWQF 2024/01/07
笔记
216.组合总和III
找出所有相加之和为 n
的 k
个数的组合,且满足下列条件:
- 只使用数字1到9
- 每个数字 最多使用一次
返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。
示例 1:
输入: k = 3, n = 7
输出: [[1,2,4]]
解释:
1 + 2 + 4 = 7
没有其他符合的组合了。
回溯法
和上一道比较类似,到达目标长度就验证,使用startIndex来避免组合重复和重复数字。初步的剪枝也使用了相近的方法
class Solution {
private:
vector<vector<int>> result; // 存放符合条件结果的集合
vector<int> path; // 用来存放符合条件结果
void backtracking(int n, int k, int startIndex) {
if (path.size() == k) {
int sum = 0;
for(int i = 0;i < k;i++)
{
sum += path[i];
}
if(sum == n){result.push_back(path);}
return;
}
for (int i = startIndex; i <= 9 - (k - path.size()) + 1; i++) {
path.push_back(i); // 处理节点
backtracking(n, k, i + 1); // 递归
path.pop_back(); // 回溯,撤销处理的节点
}
}
public:
vector<vector<int>> combinationSum3(int k, int n) {
result.clear(); // 可以不写
path.clear(); // 可以不写
backtracking(n, k, 1);
return result;
}
};
剪枝
但是,针对这一题我们可以进一步地剪枝,容易想到,如果在递归过程中累加sum变量而不是到目标长度再验证,我们就可以在sum变量超过目标值n时直接放弃该分支回溯。
class Solution {
private:
vector<vector<int>> result; // 存放符合条件结果的集合
vector<int> path; // 用来存放符合条件结果
void backtracking(int n, int k,int sum, int startIndex) {
if(sum > n){return;}
if (path.size() == k) {
if(sum == n){result.push_back(path);}
return;
}
for (int i = startIndex; i <= 9 - (k - path.size()) + 1; i++) {
path.push_back(i); // 处理节点
backtracking(n, k,sum + i, i + 1); // 递归
path.pop_back(); // 回溯,撤销处理的节点
}
}
public:
vector<vector<int>> combinationSum3(int k, int n) {
result.clear(); // 可以不写
path.clear(); // 可以不写
backtracking(n, k,0, 1);
return result;
}
};
17.电话号码的字母组合
给定一个仅包含数字 2-9
的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例 1:
输入: digits = "23"输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]
回溯算法
使用回溯法解决组合问题的常规应用,没什么好说的,代码如下:
class Solution {
private:
vector<string> result; // 存放符合条件结果的集合
string path; // 用来存放符合条件结果
const string letterMap[10] = {
"", // 0
"", // 1
"abc", // 2
"def", // 3
"ghi", // 4
"jkl", // 5
"mno", // 6
"pqrs", // 7
"tuv", // 8
"wxyz", // 9
};
void backtracking(string digits,int stringIndex) {
if (path.size() == digits.size()) {
result.push_back(path);
return;
}
string ABC = letterMap[digits[stringIndex] - '0'];
for (int i = 0; i < ABC.size(); i++) {
path.push_back(ABC[i]); // 处理节点
backtracking(digits,stringIndex + 1); // 递归
path.pop_back(); // 回溯,撤销处理的节点
}
}
public:
vector<string> letterCombinations(string digits) {
if(digits.size() == 0)return result;
backtracking(digits,0);
return result;
}
};