题目描述
给你一个字符串 s,返回 s 的所有回文部分字串(把 s 给拆分成多个部分,每个部分都是一个回文串)
例一:
输入: s = "aab"
输出: [["a","a","b"],["aa","b"]]
例二:
输入: s = "a"
输出: [["a"]]
思路分析
不难看出,这又是一道回溯题,对于字符串 "aab" 来说,我们可以现在脑海中模拟一下回溯的过程:
- 从左往右取长度为 1 的字串 "a","a" 是回文,把 "a" 加入到已经选择的列表,继续递归剩下的部分 "ab"
- 对 "ab" 进行和步骤 1 同样的过程,取出 "a" 剩余 "b",取出 "ab",剩余空字符串
- 判断每次取出的字符串,如果是回文的话,才会进行假如已选列表,并执行递归过程,否则放弃掉
- 重复上述过程...
我们先写出判断是否是回文的代码:
const isPalindrome = (str) => {
if (str.length === 0) {
return false;
}
for (let i = 0, j = str.length - 1; i < j; i++, j--) {
if (str[i] !== str[j]) {
return false;
}
}
return true;
};
然后是我们的回溯代码:
初始化时:
- 待选集合是字符串 s
- 已选的集合为空
递归的过程:
- 遍历待选字符串,分别取出长度为 1,2,3...s.length 的回文子串
- 把当前取出的回文串加入到已选集合中
- 剩下的串继续执行递归过程
递归出口:待选字符串为空时停止,将已选的集合 push 到结果数组中
AC 代码
var partition = function (s) {
let result = [];
const backtrace = (str, current) => {
if (str === "") {
result.push(current);
return;
}
for (let i = 1; i <= str.length; i++) {
let arr = [...current];
let subStr = str.slice(0, i);
if (isPalindrome(subStr)) {
arr.push(subStr);
backtrace(str.slice(i), arr);
} else {
continue;
}
}
};
backtrace(s, []);
return result;
};
总结
这道题和
- permutations
- subsets
- Letter Combinations of a Phone Number
- Check If a String Contains All Binary Codes of Size K
这四道题都用到了回溯算法,大家可以放在一起作比较,理解回溯算法的写法和思路,最终总结出一套属于自己的方法论。
本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情