题目来源:https://leetcode.cn/problems/palindrome-partitioning/description/
C++题解1: 直接回溯。
- 传入参数:字符串s和已切割的位置startind;
- 终止条件:已切割的位置大于等于字符串的长度范围,保存已切割好的字符串组;
- 单层逻辑:将切割的位置 j 从 startind+1 开始不断往后移,如果被切下来的这段是回文串的话则进行下一步回溯,不是的话则 j 继续后移。
class Solution {
public:
vector<vector<string>> res;
vector<string> path;
bool ishui(string seg) {
int len = seg.size();
for(int i = 0; i < len/2; i++) {
if(seg[i] != seg[len - i - 1]) return false;
}
return true;
}
void backtracking(string s, int startind) {
if(startind >= s.size()) {
res.push_back(path);
return ;
}
for(int j = startind + 1; j <= s.size(); j++){
string seg = s.substr(startind, j - startind);
if(ishui(seg)) {
path.push_back(seg);
backtracking(s, j);
path.pop_back();
}
}
return ;
}
vector<vector<string>> partition(string s) {
backtracking(s, 0);
return res;
}
};
C++题解2(来源代码随想录):进行了优化处理。例如给定字符串"abcde"
, 在已知"bcd"
不是回文字串时, 不再需要去双指针操作"abcde"
而可以直接判定它一定不是回文字串。具体来说, 给定一个字符串s
, 长度为n
, 它成为回文字串的充分必要条件是s[0] == s[n-1]
且s[1:n-1]
是回文字串。
class Solution {
private:
vector<vector<string>> result;
vector<string> path; // 放已经回文的子串
vector<vector<bool>> isPalindrome; // 放事先计算好的是否回文子串的结果
void backtracking (const string& s, int startIndex) {
// 如果起始位置已经大于s的大小,说明已经找到了一组分割方案了
if (startIndex >= s.size()) {
result.push_back(path);
return;
}
for (int i = startIndex; i < s.size(); i++) {
if (isPalindrome[startIndex][i]) { // 是回文子串
// 获取[startIndex,i]在s中的子串
string str = s.substr(startIndex, i - startIndex + 1);
path.push_back(str);
} else { // 不是回文,跳过
continue;
}
backtracking(s, i + 1); // 寻找i+1为起始位置的子串
path.pop_back(); // 回溯过程,弹出本次已经填在的子串
}
}
void computePalindrome(const string& s) {
// isPalindrome[i][j] 代表 s[i:j](双边包括)是否是回文字串
isPalindrome.resize(s.size(), vector<bool>(s.size(), false)); // 根据字符串s, 刷新布尔矩阵的大小
for (int i = s.size() - 1; i >= 0; i--) {
// 需要倒序计算, 保证在i行时, i+1行已经计算好了
for (int j = i; j < s.size(); j++) {
if (j == i) {isPalindrome[i][j] = true;}
else if (j - i == 1) {isPalindrome[i][j] = (s[i] == s[j]);}
else {isPalindrome[i][j] = (s[i] == s[j] && isPalindrome[i+1][j-1]);}
}
}
}
public:
vector<vector<string>> partition(string s) {
result.clear();
path.clear();
computePalindrome(s);
backtracking(s, 0);
return result;
}
};