131.分割回文串(回溯算法)
给你一个字符串 s
,请你将 s
分割成一些子串,使每个子串都是
回文串
。返回 s
所有可能的分割方案。
示例 1:
输入:s = "aab" 输出:[["a","a","b"],["aa","b"]]
示例 2:
输入:s = "a" 输出:[["a"]]
class Solution {
vector<vector<string>> result; // 用于存储所有可能的分割结果
vector<string> path; // 用于存储当前的分割路径
public:
// 判断是否回文
bool isPalindrome(const string& s, int start, int end) {
for (int i = start, j = end; i < j; i++, j--) {
if (s[i] != s[j]) {
return false;
}
}
return true;
}
// 递归函数
void Back(const string& s, int startIndex) {
if (startIndex >= s.size()) { // 如果起始索引到达字符串末尾,说明找到了一个有效的分割
result.push_back(path); // 将当前的分割路径添加到结果中
return;
}
for (int i = startIndex; i < s.size(); i++) {
if (isPalindrome(s, startIndex, i)) { // 如果从startIndex到i的子串是回文串
string str = s.substr(startIndex, i - startIndex + 1); // 提取子串
path.push_back(str); // 将子串添加到当前路径中
Back(s, i + 1); // 递归地处理剩下的字符串
path.pop_back(); // 回溯,移除当前添加的子串
} else {
continue; // 如果不是回文串,则跳过当前循环,尝试下一个子串
}
}
}
// 分割回文串
vector<vector<string>> partition(string s) {
Back(s, 0); // 从索引0开始递归
return result;
}
};
代码中的主要函数是 isPalindrome
和 Back
。
-
isPalindrome
函数用于检查一个字符串从索引start
到end
的子串是否是回文串。它通过比较对称位置的字符来实现。 -
Back
函数是一个递归函数,用于找到所有可能的分割方式。它从startIndex
开始,尝试所有可能的子串,并检查它们是否是回文串。如果是,就将其添加到当前路径path
中,并递归地处理剩下的字符串。每次递归调用后,都会通过path.pop_back()
进行回溯,以便尝试其他可能的分割。 -
partition
函数是类的公共接口,它初始化递归过程,从字符串的开始位置(索引 0)调用Back
函数,并返回最终的结果result
。
1.i
和 startIndex
的含义
i
和 startIndex
是用于控制递归函数 Back
中循环和递归调用的变量。
-
i
是一个循环变量,用于遍历字符串s
。在Back
函数中,i
从startIndex
开始,一直到字符串的末尾。这个循环的目的是检查从startIndex
开始的每一个子串s[startIndex, i]
是否是一个回文串。如果是,就将其加入到当前的分割路径path
中,并递归地调用Back
函数,继续检查剩下的子串。 -
startIndex
是一个表示当前递归函数开始检查子串的起始位置的变量。在每次递归调用中,startIndex
会被更新为当前回文串的结束位置i
加一,即i + 1
。这样,下一次递归调用就会从下一个位置开始检查新的子串。 i
是用来在每次递归中遍历字符串的当前位置,试图找到一个回文子串。