题目:131. 分割回文串
思路
回溯法
切割问题:在某个地方画一个挡板,比如aab
可以画成:a|ab
,a|a|b
,每个字母之间理论上都可画一个挡板;
抽象成当前n
个字母,画一道挡板,挡板后面剩下的字母,再画一道挡板,所以可以用回溯法 解决;
注意挡板位置在字母右侧,遍历时用i
表示,比如i = 0
,位置如下:a|ab
;i = size
,位置如下:aab|
,此时已经遍历完毕;
代码
cpp
// 代码随想录说这其实是一道`hard`题目
// 自己写的哦!
class Solution {
public:
vector<vector<string>> result;
vector<string> path;
bool compare(const string& s)
{
int i, j;
int size = s.size();
for(i = 0, j = size-1; i < j; i++, j--)
{
if(s[i] != s[j])
{
return false;
}
}
return true;
}
void function(string s, int startindex)
{
int i, size;
if(startindex == s.size())
{
result.push_back(path);
return;
}
size = s.size();
for(i = startindex; i < size; i++)
{
string temp = s.substr(startindex, i-startindex+1);
// 是回文串
if(compare(temp))
{
path.push_back(temp);
function(s, i+1);
path.pop_back();
}
}
}
vector<vector<string>> partition(string s) {
result.clear();
path.clear();
function(s, 0);
return result;
}
};
判断是否回文串:双指针法 ;
注意回溯处理当前子串是指区间[startindex, i]
这部分,所以接下来调用递归应该是function(s, i+1);
,从i+1
开始;
获取子串用到函数substr()
,用法如下:
str = s.substr(pos, len);
从位置pos
开始的len
个元素(包括pos
);
难点(Carl总结)
- 切割问题可以抽象成组合问题;
- 如何模拟那些切割线;
- 切割问题中递归如何终止;
- 在递归循环中如何截取子串;
- 如何判断回文;
剪枝
还可以用动态规划的思想,逻辑是这样:
对于字符串abcde
来说,如果判断到中间段bcd
不是回文串,那么整个abcde
也必定不是回文串;