Skip to content

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

Description

@chencl1986

原题链接: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. 如果将strs用dp数组代替,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;
};

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions