题目:
给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。
回文串 是正着读和反着读都一样的字符串。
class Solution {
// 涉及到字符串的操作,可以不用 vector 数组,因为string本身就有很多操作,基本可以满足
// 这道题本身就要求了结果的类型,所以path的数据类型就定了
// 我之前的理解有一些偏差,回文串的分割,是前后有关联的,所以之前的理解需要重新整理一下
// 回文串是一组一组的,***s 分割成一些子串,使每个子串都是 回文串****,这句话没有注意
// 这道题跟之前不一样的一个点是:并不是把找到的每一个结果都放在 path 中,也就是遍历并没有都存储在path
// 但是还是都遍历了,遍历的整个实现是用下标来实现的,
// path 存放的是回文串,当且仅当 遍历到最后
private:
vector<string> path; // 这里存放的是,已经回文的子串,注意不是所有都放,而是回文的才放进来
vector<vector<string>> result;
// 这个函数判断是否为回文串
bool isPalindrome(const string& s, int start, int end)
{
for(int i = start, j = end; i < j; start++,end--)
{
if(s[i] != s[j])
{
return false;
}
}
return true;
}
// 递归参数需要传入startIndex,表示下一轮要递归遍历的起始位置
void backtracking(const string& s, int startIndex)
{
// 判断是否是回文串,如果是,则加入结果集,因为需要每一个子串都是回文串,所以只能是在for循环中判断
// 如果起始位置已经大于s的大小,就说明已经找到了一组分割方案呢
if(startIndex >= s.size())
{
result.push_back(path);
return;
}
for(int i = startIndex; i < s.size(); i++)
{
// 判断是否为回文串,是则放进 path 中,不是则 继续下一个树枝
if(isPalindrome(s, startIndex, i))
{
// 获取区间内的子串是回文串,则截取这段子串放进 path 中
string str = s.substr(startIndex, i - startIndex + 1);
path.push_back(str);
}
else
{
continue;
}
// 寻找 i+1 为起始位置的子串
backtracking(s, i+1);
path.pop_back(); // 回溯过程,弹出本次已经填在子串中的字符
}
}
public:
vector<vector<string>> partition(string s)
{
result.clear();
path.clear();
backtracking(s, 0);
return result;
}
};