递归/回溯
1. 17. 电话号码的字母组合
中等
给定一个仅包含数字 2-9
的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例 1:
输入:digits = "23" 输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]
示例 2:
输入:digits = "" 输出:[]
示例 3:
输入:digits = "2" 输出:["a","b","c"]
提示:
0 <= digits.length <= 4
digits[i]
是范围['2', '9']
的一个数字。
// 定义一个类 Solution
class Solution {
public:
// 定义一个字符串向量 v,存储数字到字母的映射关系,数字 2 到 9 分别对应不同的字母组合
vector<string> v{"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
// 定义一个字符串向量 result,用于存储所有可能的字母组合结果
vector<string> result;
// 定义一个字符串 path,用于记录当前组合的路径
string path;// 递归函数 recursive,用于生成所有可能的字母组合
void recursive(string digits, int index) {
// 递归结束条件:当 path 的长度等于输入的数字串长度时,将当前组合添加到结果中
if (path.size() == digits.size()) {
result.push_back(path);
return;
}// 根据当前数字获取对应的字母字符串
string s = v[digits[index] - '0'];// 遍历当前数字对应的每个字母
for (int i = 0; i < s.size(); ++i) {
// 将当前字母添加到 path
path.push_back(s[i]);// 递归调用,下一个数字
recursive(digits, index + 1);// 回溯:移除最后一个添加的字母,以便尝试下一个字母组合
path.pop_back();
}
}// 主函数 letterCombinations,调用递归函数并返回结果
vector<string> letterCombinations(string digits) {
// 如果输入为空,返回空的结果集
if (digits.size() == 0) return {};
// 调用递归函数,开始生成字母组合
recursive(digits, 0);// 返回所有生成的字母组合
return result;
}
};
2. 22. 括号生成
中等
数字 n
代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
示例 1:
输入:n = 3 输出:["((()))","(()())","(())()","()(())","()()()"]
示例 2:
输入:n = 1 输出:["()"]
提示:
1 <= n <= 8
class Solution {
public:
vector<string> ans; // 存储所有有效的括号组合
string cur; // 当前构建的括号组合字符串
// 回溯函数
void backtrack(string& cur, int open, int close, int n) {
// 基线条件:当当前组合的长度等于 2*n 时,意味着已生成一个有效的括号组合
if (cur.size() == 2 * n) {
ans.push_back(cur); // 将当前组合添加到结果中
return; // 返回,结束当前递归
}
// 1. 尝试添加左括号
if (open < n) { // 只有在左括号数量小于 n 时才能添加左括号
cur.push_back('('); // 将左括号添加到当前组合
backtrack(cur, open + 1, close, n); // 递归调用,更新 open 数量
cur.pop_back(); // 回溯:移除最后一个字符,尝试其他组合
}
// 2. 尝试添加右括号
if (close < open) { // 只有在右括号数量小于左括号数量时才能添加右括号
cur.push_back(')'); // 将右括号添加到当前组合
backtrack(cur, open, close + 1, n); // 递归调用,更新 close 数量
cur.pop_back(); // 回溯:移除最后一个字符,尝试其他组合
}
}
// 生成 n 对括号的主函数
vector<string> generateParenthesis(int n) {
backtrack(cur, 0, 0, n); // 初始调用,open 和 close 都为 0
return ans; // 返回所有生成的有效括号组合
}
};
解释:
- 条件
if (close < open)
确保右括号的数量不会超过左括号的数量,从而保持组合的有效性。