leetcode top100挑战, 每天不鸽一道题之 最长回文子串(4/100)

803 阅读2分钟

这是我参与更文挑战的第11天,活动详情查看: 更文挑战

题目描述

最长回文子串

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

leetcode-cn.com/problems/lo…

// 示例1 
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
// 示例2 
输入:s = "cbbd"
输出:"bb"
// 示例3
输入:s = "a"
输出:"a"
// 示例4
输入:s = "ac"
输出:"a"

标签

中心扩散法

解题分析

1. 中心扩散法

看到了一种解题思路很牛逼,我们用这种思路来解一下题目。

回文串(palindromic string)是指这个字符串无论从左读还是从右读,所读的顺序是一样的;简而言之,回文串是左右对称的。所谓最长回文子串问题,是指对于一个给定的母串

中心扩散法,顾名思义把字符串中的每一个字符都当做中心,然后根据判断条件来处理是否向左右两侧继续扩散。

我们把中心扩散法带入到题目当中。

假设传入的字符串string为 abcacdc。
暂时保存的回文子串为 res 为 '' (空字符串)
其实我们可以肉眼看出 最长的回文子串为 cac。

它是怎么得出的,我们用中心扩散法一步步看下去。
由于回文子串的中心有奇数和偶数两种类型,我们下面的代码也会检测两种。

对于可以扩散的条件为 
1. start >= 0  左侧扩散 如果扩散到0 也就是第一个字符,就可以结束了
2. end < s.length 右侧扩散 与上同理 如果扩散到字符串尾部,就可以结束了
3. s[start] === s[end]  因为他是回文子串,以中心来看,慢慢扩散出去,左右肯定是相等的 cabac  
 
第一个字符 a 
以 奇数 看待  当前遍历字符:a
我们扩散第一次: 
左侧到底,扩散结束,
接着判断是否大于保存的回文子串res, 由于此时res为空,那么 res = 'a'

以 偶数 看待  当前遍历字符:ab
同上,由于条件3,两个字符串不想等 那就不扩散了
接着判断在start end边界内的字符串 这时为空,那就直接跳过

....

第4个字符 a
以奇数看待, 当前遍历字符: a
扩散第一次:
左侧右侧都可以扩散,同时扩散取到的至 start是'c',end也是'c',满足条件 继续扩散
扩散第二次:
左右两侧可以扩散,但是扩散到的值start是'b',end也是'd', 不满足条件,就不扩散了。
然后比对长度是否比之前存储的res长,如果长那继续保存


最后 res= 'cac' 也就是最长的回文子串。
function longestPalindrome(s: string): string {
    if(s.length < 2) return s 

    let res = ''


    for(let i=0; i< s.length; i++) {
        //如果回文子串为奇数 那么传入的长度为 i到i 那就是一个字符
        //  abcba    回文子串中心为c 扩散到左右
        getString(i, i) 
        
        //如果回文子串为偶数,那么传入的长度为 i到i+1 那就是两个字符
        // abccba   回文子串中心为cc 扩散到左右
        getString(i, i+1)
    }

    function getString (start: number, end: number): void {
        // 这里一步步看
        // 在这里,把每个传入的 s.splice(start, end)字符串当成中心来看,每次扩散左右,来判断左右是否是相等的
        // 1. start >= 0  左侧扩散 如果扩散到0 也就是第一个字符,就可以结束了
        // 2. end < s.length 右侧扩散 与上同理 如果扩散到字符串尾部,就可以结束了
        // 3. s[start] === s[end]  因为他是回文子串,以中心来看,慢慢扩散出去,左右肯定是相等的 cabac  
        while(start >= 0 &&  end < s.length && s[start] == s[end]) {
            start--
            end++
        }

        // 到这里的代码有两种结果
        // 1. 第一种 左侧右侧扩散到底了
        // 2. 第二种 扩散左右的值不想等
        // 所以这里的字符串肯定是回文子串,然后题目需要最长的,需要比对每次记录的回文子串,拿最大的出来。

        if(end - start - 1 > res.length) {
            res = s.slice(start + 1, end)
        }
    }

    return res 
};

image.png

最后

从今天开始不鸽,每天一道算法题并发布文章,首先想要解决的题组为Top100,第二道题目打完收工!!