分割回文串|刷题打卡

261 阅读2分钟

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

回文串 是正着读和反着读都一样的字符串。

示例 1:

输入:s = "aab"
输出:[["a","a","b"],["aa","b"]]
示例 2:

输入:s = "a"
输出:[["a"]]

  提示:

  • 1 <= s.length <= 16
  • s 仅由小写英文字母组成

解题思路:

回文串是正着倒着看都一样的字符串,因为不考虑空格的情况,所以判断回文串的方法可以简单地写成:

 function isReverse(s) {
    return s.split('').reverse().join('') === s;
  }
  

接下来就是要判断原字符串的子字符串哪些是回文串。我们可以穷举出所有的字符串逐个判定,但是这样子在对很长的字符串的时候,穷举出的子字符串的数量会非常大,无疑会超时。

我们可以从一个开始的节点去深度搜索来找。即尽量取一个字符串的前面部分最长的字串来切割,然后剩余的部分再递归这个方法。当找到最长的一个子串作为头部是回文串的话,才接着递归取找剩余的部分。不然就把头部的长度减少看看。最坏的情况头部减到1的话就必然是回文串。然后在每个长度作为头部深度优先取找可能性,如果能分割完原字符串,就代表找到了一个结果

具体代码如下:

var partition = function(s) {
  const result  = [];

  function isReverse(s) {
    return s.split('').reverse().join('') === s;
  }
  
  function Dp(before, s) {
    if(!s) result.push(before);       //如果能找完整个字符串,就添加结果。
    for(let i=0;i<s.length;i++) {
      const head = s.slice(0, s.length-i);
      if (isReverse(head)) Dp(before.concat([head]), s.slice(s.length-i))};  //如果前面的字串是回文,就递归找剩余的部分。
  }

  Dp([], s);

  return result;
};

总结

在考虑某种前置条件成立,才可能后面部分成立的情况下,可以用深度优先搜索,在遇到不符合条件的情况下及时返回,减少运算量

本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情