Leetcode 131. 分割回文串,难度:Medium。
原题请戳这里。
题目描述
给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是回文串。返回 s 所有可能的分割方案。
回文串是正着读和反着读都一样的字符串。
示例1:
输入:s = "aab"
输出:[["a","a","b"],["aa","b"]]
示例2:
输入:s = "a"
输出:[["a"]]
提示:
1 <= s.length <= 16s仅由小写英文字母组成
思路分析
抓住本题关键字回文、返回所有分割方案,就知道本题和DFS回溯少不了关系了。
题目可以理解为切分字符串s,切出的每一个子串必须是回文串,请找出所有切分的可能。由根节点s开始,枚举出可以切分掉的所有字符组合,如果切分掉的组合不是回文串,则不继续,如果是回文串,则基于切分后剩下的子串继续切分。这样可以画出一棵n叉树,从根节点到叶子节点的一条路径即为一种子集,回溯整棵树就可以得到所有的解。
另外,本题还涉及如何快速判断是否是回文串,可以和LeetCode 5. 最长回文子串结合起来看,使用动态规划,推导状态转移方程来辅助求解。
代码参考LeetCode@笨猪爆破组题解
AC代码
/**
* @param {string} s
* @return {string[][]}
*/
var partition = function(s) {
const res = [];
const dp = new Array(s.length);
for (let i = 0; i < dp.length; i++) {
dp[i] = new Array(s.length);
}
for (let j = 0; j < s.length; j++) {
for (let i = 0; i <= j; i++) {
if (i == j) {
dp[i][j] = true;
} else if (j - i == 1 && s[i] == s[j]) {
dp[i][j] = true;
} else if (j - i > 1 && s[i] == s[j] && dp[i + 1][j - 1]) {
dp[i][j] = true;
} else {
dp[i][j] = false;
}
}
}
function dfs (temp, start) {
if (start === s.length) {
res.push(temp.slice());
return;
}
for (let i = start; i < s.length; i++) {
if (dp[start][i]) {
temp.push(s.substring(start, i +1));
dfs(temp, i + 1);
temp.pop();
}
}
}
dfs([], 0);
return res;
};
总结
本题相似题目:
用到的技巧
- 定义 dp 子问题:
dp[i][j]:从i到j的子串是否回文。dp[i][j]为真,罗列出所有的情况:i == j时,子串只有一个字符,肯定回文j-i == 1时,子串由两个字符组成,字符必须相同s[i] == s[j]j-i > 1时,子串由两个以上字符组成,s[i] == s[j],且dp[i+1][j-1]=true即除去首尾字符的剩余子串也是回文子串。
本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情