题目链接
题目描述
给你一个字符串 s,请你将 s 分割成一些 子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案
题目示例
示例 1 :
输入:s = "aab"
输出:[["a","a","b"],["aa","b"]]
示例 2 :
输入:s = "a"
输出:[["a"]]
解题思路
- 问题描述:
给定一个字符串,要求将其分割成若干子串,使得每个子串都是回文。返回所有可能的分割方案。 - 核心思路:
- 深度优先搜索(DFS):通过递归遍历所有可能的分割点。
- 回溯:在找到一个有效的回文子串后,将其加入当前路径,并继续搜索剩余部分;搜索完成后回溯,尝试其他分割方式。
- 回文判断:检查子串是否是回文,只有回文子串才能被加入路径。
- 关键步骤:
- 从字符串的第一个字符开始,逐步向后遍历。
- 对于每个位置,检查从起始点到当前位置的子串是否是回文。
- 如果是回文,将其加入路径,并递归处理剩余字符串。
- 回溯时移除最后加入的子串,尝试其他分割方式。
- 当遍历到字符串末尾时,将当前路径加入结果集。
题解代码
class Solution {
// 存储所有可能的分割方案
private final List<List<String>> ans = new ArrayList<>();
// 存储当前的分割路径
private final List<String> path = new ArrayList<>();
// 原始字符串
private String s;
public List<List<String>> partition(String s) {
this.s = s;
// 从字符串的第一个字符开始深度优先搜索
dfs(0, 0);
return ans;
}
private void dfs(int i, int start) {
// 如果已经遍历到字符串末尾,将当前路径加入结果集
if (i == s.length()) {
ans.add(new ArrayList<>(path));
return;
}
// 如果未到字符串末尾,尝试不分割当前字符,继续向后遍历
if (i < s.length() - 1) {
dfs(i + 1, start);
}
// 检查从start到i的子串是否是回文
if (isPalindrome(start, i)) {
// 如果是回文,将该子串加入当前路径
path.add(s.substring(start, i + 1));
// 从下一个字符开始新的分割
dfs(i + 1, i + 1);
// 回溯,移除最后加入的子串
path.removeLast();
}
}
// 判断子串是否是回文
private boolean isPalindrome(int left, int right) {
while (left < right) {
if (s.charAt(left++) != s.charAt(right--)) {
return false;
}
}
return true;
}
}
复杂度分析
- 时间复杂度:
- 最坏情况下,字符串的所有可能分割方式为
O(2^N)(N为字符串长度),因为每个字符都可以选择分割或不分割。 - 每次分割需要检查回文,时间复杂度为
O(N)。 - 总时间复杂度为:O(N * 2^N)。
- 最坏情况下,字符串的所有可能分割方式为
- 空间复杂度:
- 递归调用栈的最大深度为
N,因此空间复杂度为:O(N)(不考虑结果集的空间占用)。 - 结果集的空间复杂度为
O(2^N),因为最多可能有2^N种分割方案。 - 总空间复杂度为:O(N + 2^N)。
- 递归调用栈的最大深度为
623

被折叠的 条评论
为什么被折叠?



