最长回文子串 js

动态规划

思路: 如果字符串首尾字符相同且去除首尾的子串也为回文串 那么 该字符串必定为回文串。
那么首先 所有长度为1的 单个字符都为回文。
然后从长度为2开始依次遍历每个长度下的子串 ,并记录该子串是否为回文。
由于长度是从短到长,也就是遍历到的字符串其去除首尾的子串必定已经得到判断。
所以只需要判断该串的首尾字符是否相等以及其子串是否为回文即可判断该串是否为回文串。
如果是回文串记录其长度即可

代码

var longestPalindrome = function (s) {
    if (s.length < 2) return s
    let begin = 0,
        j = 0,
        n = s.length,
        max = 1,
        dp = [];
    // 初始化dp,所有长度为1的字符串都是回文串
    for (let i = 0; i < n; i++) {
        dp[i] = new Array(n).fill(true)
    }
    // 以长度从短到长开始遍历
    for (let L = 2; L <= n; L++) {
        for (let i = 0; i < n; i++) {
            j = i + L - 1
            // 右边界超出长度直接退出循环
            if (j > n - 1) break;
           
            // 如果左右边缘不相等 肯定不是回文串
            if (s[i] != s[j]) {
                dp[i][j] = false
            } else {
                // 长度为2且首尾相同肯定为回文串
                if (j - i < 3) {
                    dp[i][j] = true
                } else {
                    // 向内收缩,因为内部都已经判断过是否为回文
                    dp[i][j] = dp[i + 1][j - 1]
                }
            }
            // 如果当前是回文串且长度大于所记录的最大长度
            if (dp[i][j] && (j - i + 1) > max) {
                console.log('i',i,'j',j,s[i],s[j])
                begin = i
                max = j - i + 1
                console.log('begin',begin,'max',max)
            }
        }
    }
    return s.substr(begin,  max)
};

中心扩散

思路 动态规划是从外到内剥离,那中心扩散就是从中心往外逐层扩散。以单个字符往两边扩散,如果两边字符相等则是回文串。扩散又分两种情况 分别是以该字符为中心,和以该字符和下一个字符的空隙为中心

代码

var longestPalindrome = function (s) {
    const n = s.length
    if (n == 1) return s
    let start = 0,
        end = 0;
    const expandFcn = (left, right) => {
        while (left >= 0 && right < n && s[left] == s[right]) {
            --left;
            ++right;
        }
        // console.log('right', right, 'left', left)
        return right - left - 1
    }
    for (let i=0; i < n; i++) {
        let len = Math.max(expandFcn(i, i), expandFcn(i, i + 1))
        if (len > (end - start)) {
            start = i - parseInt((len - 1) / 2)
            end = i + parseInt(len / 2)
        }
    };
    return s.substring(start, end + 1)
};
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值