js算法题解(第七天)---LeetCode: 5.最长回文子串

312 阅读2分钟

「这是我参与2022首次更文挑战的第8天,活动详情查看:2022首次更文挑战

前言

每天至少一道算法题,死磕算法

今天我们继续深入字符串,看看字符串还有哪些其他的解题方法?

今天我们在说一个回文串的解题方法----中心扩散法

方法讲解

先来说说什么是中心扩散法

回文串的题我们了解不少了,我们一般都是从两边往中间去解题,而今天我们要讲解的就是从中心向两边去扩散

因此中心扩散法的思路是:遍历每一个索引,以这个索引为中心,利用“回文串”中心对称的特点,往两边扩散,看最多能扩散多远。

在这里要注意一个细节:回文串在长度为奇数和偶数的时候,“回文中心”的形式是不一样的。

  • 奇数回文串的“中心”是一个具体的字符,例如:回文串 "aba" 的中心是字符 "b"
  • 偶数回文串的“中心”是位于中间的两个字符的“空隙”,例如:回文串 "abba" 的中心是两个 "b" 中间的那个“空隙”。

题目

给你一个字符串 s,找到 s 中最长的回文子串。

难度: 中等

示例 1:

输入: s = "babad"
输出: "bab"
解释: "aba" 同样是符合题意的答案。

第一步:从题目中提取关键字

  • 1.从字符串中找到最长的回文子串
  • 2.只要返回一个就行了,不用全部返回

思路

  • 1.上文已经说了,我们要使用中心扩散法,因为我们的中心扩散法就专门用于这种找回文子串的
  • 2.如果字符串的length<2,那证明字符串只有一个字符,直接返回就行了
  • 3.中心扩散法要遍历所有的字符
    • 1.当前字符的奇数回文串
    • 2.当前字符的偶数回文串
    • 3.对比奇数回文串和偶数回文串结果
  • 4.要写一个中心扩散函数,传入string,左指针,右指针
    • 1.左边的字符等于右边的字符,left--,right++
    • 2.如果不相等,则跳出循环,返回回文串

题解

var centerSpread = (str, left, right) => {
    // 双指针判断条件
    while (left >= 0 && right < str.length) {
        if (str[left] === str[right]) {
            left--;
            right++;
        } else {
            break;
        }
    }
    return str.substring(left + 1, right);
};



var longestPalindrome = function (s) {
    // 如果s的length<2的话,那么证明就一个字符,所以直接返回就行了
    let length = s.length;
    if (length < 2) {
        return s;
    }
    // 定义一个结果
    let res = s.substring(0, 1);
    // 初始化最大长度,用于对比for循环中的每一次长度
    let maxLength = 1;
    // 中心扩散法遍历的字符到length-1就可以了,否则i+1就到数组边界外了
    for (let i = 0; i < length-1; i++) {
        // 奇数回文串
        let oddStr = centerSpread(s, i, i);
        // 偶数回文串
        let evenStr = centerSpread(s, i, i + 1);
        let maxStr = oddStr.length > evenStr.length ? oddStr : evenStr;
        if (maxStr.length > maxLength) {
            maxLength = maxStr.length;
            res = maxStr;
        }
    }
    return res;
};

总结

我们在使用中心扩散法的时候,要记住两点要点

  • 1.要遍历所有字符,也就是获得所有以当前这个字符扩散开的回文串
  • 2.要考虑回文串是奇数还是偶数,取决于中心是一个字符,还是字符中间的空隙

参考

【LeetCode】5.最长回文子串(中心扩散法,动态规划,超详细图文,java实现)