216. 组合总和 III
回溯法每一行都要注释一下,卡哥说的开始先终止条件,基本都是void返回值,然后循环遍历,我现在还不太懂回溯的完全过程,因此也是照葫芦画瓢在写。排列组合不仅要学会回溯,还要学会剪枝。回溯过程可以隐式也可以显式,我现在就先按照显式写,以后学会再隐式。还有就是全局变量在回溯法中真的很常见。
class Solution {
public:
// 存储一个结果
vector<int> path;
// 存储结果集合
vector<vector<int>> res;
// 回溯函数
void backtracking(int k, int n, int startIndex){
// 剪枝
if (n < 0)
return;
// 终止条件 找到k个数,不管怎么样都要终止了
if (path.size() == k){
// 如果已经满足了,那么就要加入结果集
if (n == 0){
res.push_back(path);
}
return;
}
// 从一个startIndex开始遍历,不会出现重复数据
for (int i = startIndex; i <= 9-(k-path.size()) + 1; i++){
// 注意会出现回溯过程,显式回溯还是隐式回溯(本题处是显式回溯)
n -= i;
path.push_back(i);
backtracking(k, n, i + 1);
path.pop_back();
n += i;
}
}
vector<vector<int>> combinationSum3(int k, int n) {
backtracking(k, n, 1);
return res;
}
};
17. 电话号码的字母组合
这个题表现的是多个不同的组合一起取出合适的值,因此不需要startIndex,而是需要记录一下遍历的字符串的序号。string类型的一维数组其实就是字符的二维数组。
class Solution {
public:
// map不怎么会写,先抄一下
const string letterMap[10] = {
"", // 0
"", // 1
"abc", // 2
"def", // 3
"ghi", // 4
"jkl", // 5
"mno", // 6
"pqrs", // 7
"tuv", // 8
"wxyz", // 9
};
// 结果集
vector<string> res;
void backtracking(string digits,string str,int Index){
// 一定要是==digits.size(),否则还要多加处理的过程
if (Index == digits.size()){
if (str != "")
res.push_back(str);
return;
}
int digit = digits[Index] - '0';
// string letters = letterMap[digit];
// string数组其实就是二维数组
for (int i = 0; i < letterMap[digit].size(); i++){
str.push_back(letterMap[digit][i]);
backtracking(digits, str, Index + 1);
// string 也有size(),push_back(),pop_back()函数
str.pop_back();
}
}
vector<string> letterCombinations(string digits) {
backtracking(digits, "", 0);
return res;
}
};