分割回文串
题目链接
题目
给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是回文串 。返回 s 所有可能的分割方案。
例如:
输入: "aab"
输出:
[
["a","a","b"],
["aa","b"]
]
思路
-
动态规划预处理:首先使用动态规划预处理出所有的回文子串。我们使用一个二维数组
dp
,其中dp[i][j]
表示子串s[i:j+1]
是否为回文。预处理的时间复杂度为 。 -
回溯算法:在回溯过程中,通过
dp
数组快速判断子串是否为回文。我们从字符串的起始位置开始尝试分割,对于每一个位置,若子串是回文,则将其加入当前路径,并继续对剩余部分进行递归。当到达字符串末尾时,将当前路径加入结果集。
解题方法
1. 动态规划预处理
const dp = Array.from(Array(n), () => Array(n).fill(false));
for (let right = 0; right < n; right++) {
for (let left = 0; left <= right; left++) {
if (s[left] === s[right] && (right - left <= 2 || dp[left + 1][right - 1])) {
dp[left][right] = true;
}
}
}
dp
数组初始化为false
。- 双重循环填充
dp
数组。s[left] === s[right]
表示两端字符相同,如果这两个字符相邻或中间部分是回文(即dp[left + 1][right - 1]
为true
),则dp[left][right]
设为true
。
2. 回溯函数
function backTracking(start, path) {
if (start === s.length) {
result.push([...path]);
return;
}
for (let end = start; end < s.length; end++) {
if (dp[start][end]) {
path.push(s.slice(start, end + 1));
backTracking(end + 1, path);
path.pop();
}
}
}