目录
回溯算法的题整体比较简单,有模板可以直接套。
216.组合总和III
题目链接:216.组合总和III
找出所有相加之和为
n
的k
个数的组合,且满足下列条件:
- 只使用数字1到9
- 每个数字 最多使用一次
返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。
示例 1:
输入: k = 3, n = 7 输出: [[1,2,4]] 解释: 1 + 2 + 4 = 7 没有其他符合的组合了。示例 2:
输入: k = 3, n = 9 输出: [[1,2,6], [1,3,5], [2,3,4]] 解释: 1 + 2 + 6 = 9 1 + 3 + 5 = 9 2 + 3 + 4 = 9 没有其他符合的组合了。示例 3:
输入: k = 4, n = 1 输出: [] 解释: 不存在有效的组合。 在[1,9]范围内使用4个不同的数字,我们可以得到的最小和是1+2+3+4 = 10,因为10 > 1,没有有效的组合。
回溯算法:
-
思考过程:
- 本题k相当于树的深度,9(因为整个集合就是9个数)就是树的宽度。
- 剪枝操作1:已选元素总和如果已经大于n(图中数值为4)了,那么往后遍历就没有意义了,直接剪掉。
- 剪枝操作2:for循环的范围也可以剪枝,当剩余的数已经不够 k 个数组合,进行剪枝。
-
力扣代码:
class Solution {
private:
vector<vector<int>> result;
vector<int> path;
int sum = 0;
// n:目标和。
// k:题目中要求k个数的集合。
// sum:已经收集的元素的总和,也就是path里元素的总和。
// i:下一层for循环搜索的起始位置。
void backtracking(int k, int n, int i) {
if (sum > n) { // 剪枝操作2
return;
}
if (path.size() == k) {
if (sum == n) result.push_back(path);
return; // 如果path.size() == k 但sum != targetSum 直接返回
}
for (i; i <= 9-(k-path.size())+1; i++) { // 剪枝操作1
path.push_back(i);
sum += i;
backtracking(k, n, i+1);
path.pop_back();
sum -= i;
}
}
public:
vector<vector<int>> combinationSum3(int k, int n) {
backtracking(k, n, 1);
return result;
}
};
17.电话号码的字母组合
题目链接:17.电话号码的字母组合
给定一个仅包含数字
2-9
的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例 1:
输入:digits = "23" 输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]示例 2:
输入:digits = "" 输出:[]示例 3:
输入:digits = "2" 输出:["a","b","c"]
回溯算法:
-
思考过程:
- 抽象的树形结构:
- int num = digits[i] - '0'; // 一个数字字符的ASCII码值减去'0'的ASCII码值,得到相应的整数值
- 注意:输入1 * #按键等等异常情况
-
力扣代码:
class Solution {
private:
const string letterMap[10] = {
"", // 0
"", // 1
"abc", // 2
"def", // 3
"ghi", // 4
"jkl", // 5
"mno", // 6
"pqrs", // 7
"tuv", // 8
"wxyz", // 9
};
vector<string> result;
string s;
// k:k个数的集合。
// i: 递归深度。
void backtracking(int k, const string& digits, int i) {
if (s.size() == k) {
result.push_back(s);
return;
}
int num = digits[i] - '0'; // 第 i 层递归对应的数字
string targetString = letterMap[num]; // 数字对应的字母集合大小
for (auto cha : targetString) {
s.push_back(cha);
backtracking(k, digits, i+1);
s.pop_back();
}
}
public:
vector<string> letterCombinations(string digits) {
if(digits.empty()) return result;
int k = digits.size(); // 递归深度
backtracking(k, digits, 0);
return result;
}
};
字符串中字符增删:
string a="123";
1.在字符串末尾添加一个字符
a.push_back('3'); //结果为 a="1233";
2.在字符串末尾删除一个字符
a.pop_back(); //结果为 a="12";