题目链接:131. 分割回文串
题目描述
给你一个字符串 s
,请你将 s
分割成一些子串,使每个子串都是 回文串 。返回 s
所有可能的分割方案。
回文串 是正着读和反着读都一样的字符串。
示例 1:
输入:s = "aab" 输出:[["a","a","b"],["aa","b"]]
示例 2:
输入:s = "a" 输出:[["a"]]
提示:
1 <= s.length <= 16
s
仅由小写英文字母组成
文章讲解:代码随想录
视频讲解:带你学透回溯算法-分割回文串(对应力扣题目:131.分割回文串)| 回溯法精讲!_哔哩哔哩_bilibili
题解1:回溯法
思路:使用回溯法来求解分割问题。
回溯分析:
递归函数的参数和返回值:首先创建2个变量 res 和 path,path 记录当次结果,res 记录整体结果。递归函数的返回值为 void,参数是 start,用来记录本次递归的开始位置。
递归函数的终止条件:找到叶子节点,即 start 和原字符串的长度相等,也就是找到了一个符合题目要求的结果,将这个结果存入结果数组,并返回。
单层递归的逻辑:使用 for 循环从开始位置 start 开始直到字符串末尾进行横向遍历,当前切割的子串区间为 [start, i],递归的向下纵向遍历寻找结果。
剪枝:如果当前遍历的分割子串是回文串,再继续往下遍历。
/**
* @param {string} s
* @return {string[][]}
*/
var partition = function(s) {
const res = []; // 结果数组
const path = []; // 路径
// 判断字符串 s 的 [left, right] 区间是不是回文字符串
const isPalindrome = function (left, right) {
while (left <= right && s[left] === s[right]) {
left++;
right--;
}
return left > right;
}
const backtracking = function (start) {
// 遍历到字符串的末尾,保存结果
if (start === s.length) {
res.push([...path]);
return;
}
for (let i = start; i < s.length; i++) {
// 判断当前切割的子串 [start, i] 是不是回文字符串
if (isPalindrome(start, i)) {
path.push(s.slice(start, i + 1)); // 记录路径
backtracking(i + 1); // 向下查找
path.pop(); // 回溯
}
}
}
backtracking(0);
return res;
};
分析:时间复杂度为 O(n * 2 ^ n),空间复杂度为 O(n)。
收获
学习了使用回溯法来求解分割类问题。