【前端刷题】131.分割回文串(MEDIUM)

109 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第11天,点击查看活动详情

题目(Palindrome Partitioning)

链接:https://leetcode-cn.com/problems/palindrome-partitioning
解决数:1150
通过率:72.7%
标签:字符串 动态规划 回溯 
相关公司:amazon bytedance google 

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

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

 

示例 1:

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

示例 2:

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

 

提示:

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

思路

先对示例"aab"进行分割。

  1. 我们需要一个变量start去表示分割的s(在上图中start从0,1,2开始,分别将s="aab"分割为第二行的ab, b, 空)。
  2. 需要一个数组temp去保存取走的字符(在上图分别是a,aa,aab)。
  3. 此时进行第二行分割。ab,b,空为s,回到第一步。
  4. 当为空(start不能继续加一去分割s了,start === s.length)就保存temp
  5. temp数组最后的字符释放(回溯)。 然后就可以根据公式编写基础版本的代码,得到字符的全部顺序组合:
var partition = function (s) {
  //res保存最终结果,temp表示每一个路径分支产生的结果
  var res = [], temp = [];
  var start = 0; //start表示从s的哪一位开始,这里从s的第0位开始

  // 递归函数
  partitionStr(s, start, temp, res);
  return res;
};

function partitionStr(s, start, temp, res) {
  if (start === s.length) { //递归终止条件
    res.push([...temp]);//不能直接将temp数组push,那样push的是temp的引用
    return;
  }

 
  for (var i = start; i < s.length; i++) {
    //rest是s的前i个字符(也就是取走的字符,在aab图中是第一行的a,aa,aab等)
    var rest = s.substring(start, i + 1);
    temp.push(rest);
    //保存了前i个字符(rest)就继续从第i+1开始分割
    partitionStr(s, i + 1, temp, res);
    temp.pop();
  }
}

然后考虑题目是需要保证每一个顺序组合是回文串,所以增加一个判断——是回文串才会将restpush进temp数组,不是就不继续递归这条路径。

var partition = function (s) {
  var res = [];
  partitionStr(s, 0, [], res);
  return res;
};

function partitionStr(s, start, temp, res) {
  if (start === s.length) {
    res.push([...temp]);
    return;
  }

  for (var i = start; i < s.length; i++) {
    //判断当前的rest是否是回文串
    if (isPalindrome(s, start, i)) {
      temp.push(s.substring(start, i + 1));
      partitionStr(s, i + 1, temp, res);
      temp.pop();
    } else {
      continue;
    }
  }
}

var isPalindrome = function (s, l, r) {
  while (l <= r) {
    if (s[l] !== s[r]) return false;
    l++;
    r--;
  }
  return true;
};