Solution 1
整个题就是之前既有的DFS的模式题,深度枚举所有的拆分方案,并要求所有的子串都满足回文要求,可以通过提前判断每个字符串是否回文向下搜索进行剪枝。
官方题解中,结合了 0005. Longest Palindromic Substring 的动态规划思路进一步简化了判断流程。
- 时间复杂度: O ( N × 2 N ) O(N \times 2^N) O(N×2N),其中 N N N是输入字符串的长度,子串生成和回文串判断需要线性复杂度,DFS最坏情况下需要全枚举。
- 空间复杂度: O ( N ) O(N) O(N),其中 N N N是输入字符串的长度,递归的函数占用,最坏情况下每个字符占一次递归调用
class Solution {
public:
vector<vector<string>> partition(string s) {
vector<vector<string>> ans;
vector<string> temp;
dfs(ans, temp, s, 0);
return ans;
}
private:
void dfs(vector<vector<string>> & ans, vector<string> & temp, string & s, int start) {
if (start >= s.size()) {
ans.push_back(temp);
return;
}
for (int i = start; i < s.size(); i++) {
if (isPalindrome(s, start, i)) {
// cout << start << " " << i << " " << s << " " << s.substr(start, i - start + 1) << endl;
temp.push_back(s.substr(start, i - start + 1));
dfs(ans, temp, s, i + 1);
temp.pop_back();
}
}
}
bool isPalindrome(string & s, int start, int i) {
int head = start, tail = i;
// cout << head << " " << tail << endl;
while (head < tail) {
if (s[head] != s[tail]) {
return false;
}
head++;
tail--;
}
return true;
}
};
Solution 2
根据官方题解,利用 0005. Longest Palindromic Substring 的思路,保存所有的小长度字符串的状态,只需要根据边界状态和内部子串状态进行回文串判断。
- 时间复杂度: O ( N × 2 N ) O(N \times 2^N) O(N×2N),其中 N N N是输入字符串的长度,子串生成需要线性复杂度,DFS最坏情况下需要全枚举。
- 空间复杂度: O ( N 2 ) O(N^2) O(N2),其中 N N N是输入字符串的长度,函数调用需要线性复杂度,此外还有一个dp数组
class Solution {
public:
vector<vector<string>> partition(string s) {
vector<vector<string>> ans;
vector<string> temp;
vector<vector<bool>> dp(s.size(), vector<bool>(s.size(), false));
// dfs(ans, temp, s, 0);
dfs2(ans, temp, s, 0, dp);
return ans;
}
private:
void dfs2(vector<vector<string>> & ans, vector<string> & temp, string & s, int start, vector<vector<bool>> & dp) {
if (start >= s.size()) {
ans.push_back(temp);
return;
}
for (int i = start; i < s.size(); i++) {
// 实际上就是先迭代尾边界
if (s[start] == s[i] && (i - start <= 2 || dp[start + 1][i - 1])) {
// cout << start << " " << i << " " << s << " " << s.substr(start, i - start + 1) << endl;
dp[start][i] = true;
temp.push_back(s.substr(start, i - start + 1));
dfs2(ans, temp, s, i + 1, dp);
temp.pop_back();
}
}
}
};
Solution 3
Solution 1的Python实现
class Solution:
def partition(self, s: str) -> List[List[str]]:
def dfs(start: int) -> None:
nonlocal ans
nonlocal temp
if start >= len(s):
ans.append(copy.deepcopy(temp))
return
for i in range (start, len(s)):
if isPalindrome(start, i):
# print("DO", start, i, s[start: i + 1])
temp.append(s[start: i + 1])
dfs(i + 1)
temp.pop()
def isPalindrome(start, i):
# print("TEST", start, i, s[start: i + 1])
head, tail = start, i
while head < tail:
if s[head] != s[tail]: return False
head += 1
tail -= 1
return True
ans = list()
temp = list()
dfs(0)
return ans
Solution 4
Solution 2的Python实现
class Solution:
def partition(self, s: str) -> List[List[str]]:
def dfs2(start: int) -> None:
nonlocal ans
nonlocal temp
nonlocal dp
if start >= len(s):
ans.append(copy.deepcopy(temp))
return
for i in range (start, len(s)):
if s[start] == s[i] and (i - start <= 2 or dp[start + 1][i - 1]):
# print("DO", start, i, s[start: i + 1])
dp[start][i] = True
temp.append(s[start: i + 1])
dfs2(i + 1)
temp.pop()
ans = list()
temp = list()
dp = [[False] * len(s) for i in range(len(s))]
# dfs(0)
dfs2(0)
return ans