描述
给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。
回文串 是正着读和反着读都一样的字符串。
示例 1:
输入:s = “aab”
输出:[[“a”,”a”,”b”],[“aa”,”b”]]
示例 2:
输入:s = “a”
输出:[[“a”]]
提示:
1 <= s.length <= 16
s 仅由小写英文字母组成
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/palindrome-partitioning
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解
C++代码
class Solution {
public:
vector<vector<string>> partition(string s) {
vector<vector<string>> res; // 用于存储结果
vector<string> path; // 用于存储当前的分割方案
dfs(s, 0, path, res); // 深度优先搜索
return res;
}
void dfs(string s, int start, vector<string>& path, vector<vector<string>>& res) {
if (start == s.size()) { // 如果已经遍历完整个字符串
res.push_back(path); // 将当前分割方案加入结果中
return;
}
for (int i = start; i < s.size(); i++) { // 从start开始遍历到字符串末尾
if (isPalindrome(s, start, i)) { // 如果[start, i]这个子串是回文串
path.push_back(s.substr(start, i - start + 1)); // 将这个子串加入当前分割方案
dfs(s, i + 1, path, res); // 递归处理下一段字符串
path.pop_back(); // 回溯,将刚刚加入的子串从当前分割方案中删除
}
}
}
bool isPalindrome(string s, int left, int right) { // 判断子串是否为回文串
while (left < right) {
if (s[left++] != s[right--]) {
return false;
}
}
return true;
}
};
这道题的思路是深度优先搜索,具体来说,我们从字符串的开头开始遍历,对于每个位置,我们考虑以它为起点的所有子串。如果这个子串是回文串,我们就将它加入当前的分割方案中,然后递归处理下一段字符串。如果当前的分割方案已经包含了整个字符串,那么我们就将它加入结果中。
在实现中,我们使用了一个辅助函数isPalindrome
来判断一个子串是否为回文串,它的实现很简单,就是从两端开始往中间扫描,如果发现不相等的字符,就说明这个子串不是回文串。
在深度优先搜索的过程中,我们使用了两个辅助变量path
和res
,分别用来存储当前的分割方案和所有的结果。每次递归调用时,我们都将当前的分割方案作为参数传入,如果当前的分割方案已经包含了整个字符串,那么我们就将它加入结果中。注意,在递归处理下一段字符串之前,我们需要将刚刚加入的子串从当前分割方案中删除,这个操作叫做回溯。
Python代码
class Solution:
def partition(self, s: str) -> List[List[str]]:
res = [] # 用于存储结果
path = [] # 用于存储当前的分割方案
self.dfs(s, 0, path, res) # 深度优先搜索
return res
def dfs(self, s: str, start: int, path: List[str], res: List[List[str]]):
if start == len(s): # 如果已经遍历完整个字符串
res.append(path[:]) # 将当前分割方案加入结果中
return
for i in range(start, len(s)): # 从start开始遍历到字符串末尾
if self.isPalindrome(s, start, i): # 如果[start, i]这个子串是回文串
path.append(s[start:i+1]) # 将这个子串加入当前分割方案
self.dfs(s, i+1, path, res) # 递归处理下一段字符串
path.pop() # 回溯,将刚刚加入的子串从当前分割方案中删除
def isPalindrome(self, s: str, left: int, right: int) -> bool: # 判断子串是否为回文串
while left < right:
if s[left] != s[right]:
return False
left += 1
right -= 1
return True