Skip to main content

分割回文串

Tips

题目类型: BackTracking

题目

给你一个字符串 s, 请你将 s 分割成一些子串, 使每个子串都是回文串. 返回 s 所有可能的分割方案.

提示:
  • 1 <= s.length <= 16
  • s 仅由小写英文字母组成
示例
输入: s = 'google'
输出: [
['g', 'o', 'o', 'g', 'l', 'e'],
['g', 'oo', 'g', 'l', 'e'],
['goog', 'l', 'e'],
]
输入: s = 'aab'
输出: [
['a', 'a', 'b'],
['aa', 'b'],
]
输入: s = 'a'
输出: [['a']]

题解

直接拿回溯的框架一套, 啪的一下就把题解了. 暗自窃喜中, 发现提交后内存只击败了 17.99%. 感觉不妙, 遂看了答案, 问题出现在每次回溯中执行一次 validPalindrome 过于浪费.

更优雅的解法是使用记忆化或者动态规划, 当然这个解法无伤大雅, 直接看注释.

/**
* @param {string} s
* @return {string[][]}
*/
var partition = function (s) {
const n = s.length
const res = []

const dfs = (begin, track) => {
// begin 走到头了, 说明一趟遍历完了, 可以收割
if (begin === n) {
res.push(track)
return
}

for (let i = begin; i < n; i++) {
const word = s.slice(begin, i + 1)

// 如果 word 是回文, 便加入 track 豪华午餐, 继续回溯
if (validPalindrome(word)) {
track.push(word)
dfs(i + 1, track.slice())
track.pop()
}
}
}

dfs(0, [])
return res
}

var validPalindrome = function (word) {
const n = word.length
let left = 0
let right = n - 1

while (left < right) {
if (word[left++] !== word[right--]) return false
}

return true
}