一、最长回文子串

257 阅读2分钟

前言

今天是我们开始更文的第一天,只许成功,不许失败,所以挑了一个已经有解题思路的动态规划题目:

求最长回文字符子串

在此就不对题目进行详细描述了,直接开始我的表演吧:

找规律

  • 1、对于回文字符串ababa来说,除去首尾字符以后(bab)也同样是回文字符串;

  • 2、如果字符串长度为1,那必定是回文,不做赘述;

  • 3、所以我们对于指定长度n的字符串来说,第一步就是要看他首尾字符是否相等,假设该段字符串在总字符串中的起始索引为i,终止索引为j,其中因为长度为n,所以j = n - i - 1;判断标准为s[i] == s[j]

  • 4、接着上一步,如果首尾字符串相等了,那我们就需要看除去首尾字符的中间子串是否为回文,也就是起始索引 + 1,终止索引 - 1,往中间靠,如果不相等,那这段字符串就排除;

  • 5、重复上面两步过程,直到中间只剩1个字符或者2个字符,为啥呢?因为只剩两个字符我们就可以直接判断出是否符合回文的要求。

上代码

var longestPalindrome = function(s) {
    // 记录字符串总长度
    const len = s.length;
    // 记录当前最长回文子串
    let res = "";
    // 二维数组来表示一段字符是否为回文,是则true,否则false
    // 如[i][j]表示从i索引到j索引的字符串是否为回文
    const dp = new Array(len);
    for (let i = 0; i < len; i++) {
        dp[i] = [];
    }
    // 这里l千万别看成数字1哦
    for (let l = 1; l <= len; l++) {
        // 长度为l,起始索引最多可以到达 len - l
        for (let i = 0; i <= len - l; i++) {
            // 通过起始索引i和字符长度l得到终止索引j
            let j = i + l - 1;
            if (l == 1) {
                // 只有一个字符,那肯定是回文
                dp[i][j] = true;
            } else if (l == 2) {
                // 两个字符的时候,比较首尾是否相等即可
                dp[i][j] = s[i] == s[j];
            } else {
                // 就是规律中所说的3、4步
                dp[i][j] = s[i] == s[j] && dp[i+1][j-1];
            }
            // 从索引i到索引j的字符串为回文,且这段长度比当前最长回文子串长,则更新这段字符串为最长
            if (dp[i][j] && j - i + 1 > res.length) {
                res = s.slice(i, j+1);
            }
        }
    }
    return res;
};

自我鼓励

  • 不坚持怎么会坚挺
  • 光羡慕是没有用的,我们要行动起来