(前端必会)最长回文子串

743 阅读3分钟

本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金。


最长回文子串

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

LeetCode热题100 的第五题 , 也是一道极容易出现在前端面试中的算法题 . 命题关键字:字符串、动态规划

image.png

不高的通过率让大家都望而却步 . 学习前端 , 我们不仅有艺术性的思维 , 也得有精妙的逻辑 , 而这道题 , 便可以让我们历练一番 .

**示例 1:**

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

**示例 2:**

输入: s = "cbbd"
输出: "bb"

那么解题开始 .

放弃思考,尊重本能

直接暴力开干

定义两个指针 i 和 j,用这两个指针嵌套两层循环,尝试枚举出给定字符串对应的所有可能的子序列,判断每一个子序列是否回文:若回文且长度已经超越当前的长度最大值,则更新长度最大值,并记录该子串的两个端点。当所有的子串枚举结束时,我们也就得到了最大长度的回文子串。

//建议跳过
var longestPalindrome = function(s) {
    function isPalindrome(str) {
    var len  = str.length
    var middle = parseInt(len/2)
    for(var i = 0;i<middle;i++){
        if(str[i]!=str[len-i-1]){
            return false
        }
    }
    return true
    }
    var ans = '';
    var max = 0;
    var len = s.length
    for(var i = 0;i<len;i++){
        for(var r = i+1;r<=len;r++){
            var tmpStr = s.substring(i,r)
            if(isPalindrome(tmpStr) && tmpStr.length > max){
                ans = s.substring(i,r)
                max = tmpStr.length;
            }
        }
    }
    return ans;
};

但是咱得优雅 , 暴力不是解决问题的唯一方法 .

拒绝蛮干 , 开始动脑

题干中的 '最长' 二字 , 见到最值 , 就得开始考虑动态规划了 . 而给我们一个字符串 , 假如这字符串就是一个回文串 , 那么最长回文子串就是他本身了 , 而他的内部又会有着 1/2 他长度的回文子串 .

所以思路来了 .

  1. 以最中央的点为核心 , 设俩指针不断向两边发散 , 我们就可以对每次发散的字符串进行判断 , 从而找到以该点而形成的回文串
  2. 那么再进行发散 , 我们把每个点都当做中心点 , 开始进行发散 , 那么我们就可以得到每个点上所对应的回文串 .
  3. 到了这一步 , 那就剩下代码复现了 . 在不断试错中解决边界问题与一些小瑕疵 .

虽然我并不是聪明的那一个 , 但我是比较喜欢汲取他人经验的那一个 , 总是在看题解中学习 .

/**
 * @param {string} s
 * @return {string}
 */
var longestPalindrome = function(s) {
        if (s.length<2){
            return s
        }
        let res = ''
        for (let i = 0; i < s.length; i++) {
            // 回文子串长度是奇数
            helper(i, i)
            // 回文子串长度是偶数
            helper(i, i + 1) 
        }

        function helper(m, n) {
            while (m >= 0 && n < s.length && s[m] == s[n]) {
                m--
                n++
            }
            // 注意此处m,n的值循环完后  是恰好不满足循环条件的时刻
            // 此时m到n的距离为n-m+1,但是mn两个边界不能取 所以应该取m+1到n-1的区间  长度是n-m-1
            if (n - m - 1 > res.length) {
                // slice也要取[m+1,n-1]这个区间 
                res = s.slice(m + 1, n)
            }
        }
        return res
};

作者:qing-chen-4a
链接:https://leetcode-cn.com/problems/longest-palindromic-substring/solution/chao-jian-dan-de-zhong-xin-kuo-san-fa-yi-qini/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

这就是大佬的解题 , 这是万千题解中最与我登对的一个 . 我学会了 , 以后说不定也会忘却 , 但我写的博客会永远记录我的思考 .

「欢迎在评论区讨论,掘金官方将在掘力星计划活动结束后,在评论区抽送100份掘金周边,抽奖详情见活动文章」