131. 分割回文串(昨天的题放在今天一起做)
给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。 回文串 是正着读和反着读都一样的字符串。
示例 1: 输入:s = "aab" 输出:[["a","a","b"],["aa","b"]] 示例 2: 输入:s = "a" 输出:[["a"]]
提示:
- 1 <= s.length <= 16
- s 仅由小写英文字母组成
思路
- 定义数据结构 result:存储所有满足条件的组合。 current:存储当前正在构建的组合。
- 辅助函数:检查回文 定义一个函数来检查一个字符串是否是回文。
- 回溯函数 该函数主要执行以下操作:
结束条件:如果字符串 s 为空,说明已找到一个有效的组合,将其添加到 result。 选择与回溯:从字符串 s 中选择一个回文子串,并加入到 current。然后递归调用回溯函数。最后,撤销这一选择。
- 主函数 partition 在主函数中,调用回溯函数,并最终返回 result。
题解
class Solution {
private:
vector<vector<string>> result;
vector<string> current;
// 辅助函数:检查回文
bool isPalindrome(const string& s) {
int left = 0, right = s.size() - 1;
while (left < right) {
if (s[left] != s[right]) return false;
left++;
right--;
}
return true;
}
public:
void backtracking(string& s, int start) {
// 结束条件
if (start == s.size()) {
result.push_back(current);
return;
}
for (int end = start; end < s.size(); ++end) {
// 选择一个子串 [start, end]
string sub = s.substr(start, end - start + 1);
// 检查是否为回文
if (isPalindrome(sub)) {
current.push_back(sub); // 选择
backtracking(s, end + 1); // 回溯
current.pop_back(); // 撤销选择
}
}
}
vector<vector<string>> partition(string s) {
backtracking(s, 0);
return result;
}
};
93. 复原 IP 地址
有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 '.' 分隔。
- 例如:"0.1.2.201" 和 "192.168.1.1" 是 有效 IP 地址,但是 "0.011.255.245"、"192.168.1.312" 和 "192.168@1.1" 是 无效 IP 地址。
- 给定一个只包含数字的字符串 s ,用以表示一个 IP 地址,返回所有可能的有效 IP 地址,这些地址可以通过在 s 中插入 '.' 来形成。你 不能 重新排序或删除 s 中的任何数字。你可以按 任何 顺序返回答案。 示例 1: 输入:s = "25525511135" 输出:["255.255.11.135","255.255.111.35"] 示例 2: 输入:s = "0000" 输出:["0.0.0.0"] 示例 3: 输入:s = "101023" 输出:["1.0.10.23","1.0.102.3","10.1.0.23","10.10.2.3","101.0.2.3"] 提示:
- 1 <= s.length <= 20
- s 仅由数字组成
思路
从字符串的第一个字符开始,逐步尝试选择 1-3 个数字作为 IP 地址的一个部分,然后进入下一层递归。在递归过程中,需要注意以下几点:
- 每个 IP 地址部分应是一个 0-255 之间的整数。
- 如果一个 IP 地址部分以 '0' 开头,那么它只能是 '0'。
- 最终的 IP 地址必须有 4 部分。
- 其他部分参考上题
题解
class Solution {
private:
vector<string> result;
vector<string> current;
// 辅助函数:检查子串是否有效
bool isValid(const string& s) {
if (s.empty() || s.size() > 3 || (s.size() > 1 && s[0] == '0') || stoi(s) > 255) {
return false;
}
return true;
}
public:
void backtracking(string& s, int start) {
// 结束条件:找到 4 个有效部分且使用了所有字符
if (current.size() == 4 && start == s.size()) {
result.push_back(current[0] + '.' + current[1] + '.' + current[2] + '.' + current[3]);
return;
}
// 结束条件:找到 4 个部分但未使用所有字符,或使用了所有字符但未找到 4 个部分
if (current.size() == 4 || start == s.size()) {
return;
}
for (int end = start; end < s.size(); ++end) {
// 选择一个子串 [start, end]
string sub = s.substr(start, end - start + 1);
// 检查是否有效
if (isValid(sub)) {
current.push_back(sub); // 选择
backtracking(s, end + 1); // 回溯
current.pop_back(); // 撤销选择
}
}
}
vector<string> restoreIpAddresses(string s) {
backtracking(s, 0);
return result;
}
};