chencl1986 / Blog

Welcome to lee's blog.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

LeetCode题解:647. 回文子串,动态规划,JavaScript,详细注释

chencl1986 opened this issue · comments

原题链接:647. 回文子串

解题思路:

  1. 假设输入aabaca,用这段代码生成子串:
/**
 * @param {string} s
 * @return {number}
 */
var countSubstrings = function (s) {
  let strs = []; // 用于生成所有子串
  for (let j = 0; j < s.length; j++) {
    strs.push(new Array(s.length).fill(new Array(s.length).fill(' ').join('')));
    for (let i = 0; i <= j; i++) {
      // 生成子串的代码
      strs[i][j] = s.slice(i, j + 1);
      while (strs[i][j].length < s.length) {
        strs[i][j] += ' ';
      }
    }
    // 打印每次循环生成的结果
    console.log(strs);
  }
  // 打印标记好的子串结果
  console.log(strs);
};
  1. 可以看到最终打印的结果如下:

如果查看每一层循环结束时,打印生成的子串,会发现实际上是从左到右按列生成的。

[
  [ 'a     ', 'aa    ', 'aab   ', 'aaba  ', 'aabac ', 'aabaca' ],
  [ '      ', 'a     ', 'ab    ', 'aba   ', 'abac  ', 'abaca ' ],
  [ '      ', '      ', 'b     ', 'ba    ', 'bac   ', 'baca  ' ],
  [ '      ', '      ', '      ', 'a     ', 'ac    ', 'aca   ' ],
  [ '      ', '      ', '      ', '      ', 'c     ', 'ca    ' ],
  [ '      ', '      ', '      ', '      ', '      ', 'a     ' ]
]
  1. 如果将strsdp数组代替,dp[i][j]用于标记当前子串是否回文子串,有3种可能情况:

    • i === j,只有一个字母,必然为回文子串。
    • j - i === 1,有两个字母,当s[i] === s[j]时,即两个字母相等时,是回文子串。
    • j - i > 1,有两个以上字母时,先判断s[i] === s[j],也就是子串的首尾两个字母相等。同时如果dp[i + 1][j - 1],即矩阵左下方,也就是对应去除首尾字母后的子串,也是回文子串。那么当前字符串一定是回文子串。
/**
 * @param {string} s
 * @return {number}
 */
var countSubstrings = function (s) {
  let count = 0; // 统计所有回文子串数量
  let dp = []; // 将所有生成的子串用矩阵标记,是回文子串的标记为true,其余为false

  // 标记每行的子串
  for (let j = 0; j < s.length; j++) {
    // 默认一行中所有的子串都是false
    dp.push(new Array(s.length).fill(false));

    // 标记每列的子串,
    for (let i = 0; i <= j; i++) {
      // 两个索引相等时,子串只有一个字母,此时必然是是回文串
      if (j === i) {
        count++; // 将子串计数
        dp[i][j] = true; // 在矩阵中标记回文子串
      }
      // 有两个字母,且两个字母相等,是回文串
      else if (j - i === 1 && s[i] === s[j]) {
        count++; // 将子串计数
        dp[i][j] = true; // 在矩阵中标记回文子串
      } else if (
        // 字符串数量多于两个
        j - i > 1 &&
        // 首尾两个字母相等
        s[i] === s[j] &&
        // 且dp[i + 1][j - 1],也就是剔除首尾后的子串是回文子串
        dp[i + 1][j - 1]
      ) {
        count++; // 将子串计数
        dp[i][j] = true; // 在矩阵中标记回文子串
      }
    }
  }

  return count;
};