Go语言的LeetCode刷题之旅-005-最长回文子串

Go语言的LeetCode刷题之旅-005-最长回文子串


题目:

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为1000。

示例 1:

输入: "babad"
输出: "bab"
注意: "aba"也是一个有效答案。

示例 2:

输入: "cbbd"
输出: "bb"

思路:

题目要求寻找字符串中的最长回文。 当然,我们可以使用下面的程序判断字符串s[i:j+1]是否是回文。

func isPalindromic(s *string, i, j int ) bool {
    for  i< j {
        if (*s)[i] != (*s)[j] {
            return false
        } 
        i++
        j--
    }
    return true
}

但是,这样就没有利用回文的一下特点,假定回文的长度为l,x为任意字符

  1. 当l为奇数时,回文的正中间段只会是,“x”,或“xxx”,或“xxxxx”,或…
  2. 当l为偶数时,回文的正中间段只会是,“xx”,或“xxxx”,或“xxxxxx”,或…
  3. 同一个字符串的任意两个回文substring的正中间段,不会重叠。

Go代码:

package problem0005

func longestPalindrome(s string) string {
    if len(s) < 2 { // 肯定是回文,直接返回
        return s
    }

    // 最长回文的首字符索引,和最长回文的长度
    begin, maxLen := 0, 1

    // 在 for 循环中
    // b 代表回文的**首**字符索引号,
    // e 代表回文的**尾**字符索引号,
    // i 代表回文`正中间段`首字符的索引号
    // 在每一次for循环中
    // 先从i开始,利用`正中间段`所有字符相同的特性,让b,e分别指向`正中间段`的首尾
    // 再从`正中间段`向两边扩张,让b,e分别指向此`正中间段`为中心的最长回文的首尾
    for i := 0; i < len(s); { // 以s[i]为`正中间段`首字符开始寻找最长回文。
        if len(s)-i <= maxLen/2 {
            // 因为i是回文`正中间段`首字符的索引号
            // 假设此时能找到的最长回文的长度为l, 则,l <= (len(s)-i)*2 - 1
            // 如果,len(s)-i <= maxLen/2 成立
            // 则,l <= maxLen - 1
            // 则,l < maxLen
            // 所以,无需再找下去了。
            break
        }

        b, e := i, i
        for e < len(s)-1 && s[e+1] == s[e] {
            e++
            // 循环结束后,s[b:e+1]是一串相同的字符串
        }

        // 下一个回文的`正中间段`的首字符只会是s[e+1]
        // 为下一次循环做准备
        i = e + 1

        for e < len(s)-1 && b > 0 && s[e+1] == s[b-1] {
            e++
            b--
            // 循环结束后,s[b:e+1]是这次能找到的最长回文。
        }

        newLen := e + 1 - b
        // 创新记录的话,就更新记录
        if newLen > maxLen {
            begin = b
            maxLen = newLen
        }
    }

    return s[begin : begin+maxLen]
}

你可能感兴趣的:(Golang,LeetCode,算法)