【leetcode--golang】5. 最长回文子串

题目

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

示例

示例 1:输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
示例 2:输入: "cbbd"
输出: "bb"

解决方案

方法一、动态规划
我们首先观察如何避免在验证回文时进行不必要的重复计算。考虑“ababa” 这个示例。如果我们已经知道“bab” 是回文,那么很明显,ababa” 一定是回文,因为它的左首字母和右尾字母是相同的。我们给出 P(i,j) 的定义如下:
在这里插入图片描述
因此,P(i, j) = ( P(i+1, j-1) and S(i) == S(j) )
基本示例如下:
P(i, i) = trueP(i,i)=true
P(i, i+1) = ( S(i) == S(i+1) )
这产生了一个直观的动态规划解法,我们首先初始化一字母和二字母的回文,然后找到所有三字母回文,并依此类推…复杂度分析时间复杂度:O(n^2), 这里给出我们的运行时间复杂度为 O(n^2) 。空间复杂度:O(n^2), 该方法使用 O(n^2) 的空间来存储表。

方法二:中心扩展算法
事实上只需使用恒定的空间,我们就可以在 O(n^2) 的时间内解决这个问题。我们观察到回文中心的两侧互为镜像。因此,回文可以从它的中心展开,并且只有 2n - 1 个这样的中心。你可能会问,为什么会是 2n - 1个,而不是 n个中心?原因在于所含字母数为偶数的回文的中心可以处于两字母之间“abba” 的中心在两个‘b’之间)。

func longestPalindrome(s string) string {
    //    odd number
    n := len(s)
    if n == 0 {
        return ""
    }
    if n == 1 {
        return s
    }

    var res1, res2 int
    var tmp1, tmp2 int
    var str1, str2 string

    for i := 0; i < n-1; i++ {
        tmp1 = 1
        l1 := i - 1
        r1 := i + 1
        for {
            //            fmt.Println("##i=%d", i)
            if l1 >= 0 && r1 <= n-1 {
                //                fmt.Println("s[l1]=%v, s[i]=%v, s[r1]=%v", string(s[l1]), string(s[i]), string(s[r1]))
                if s[l1] == s[r1] {
                    tmp1 += 2
                    l1--
                    r1++
                } else {
                    break
                }
            } else {
                break
            }

        }

        if tmp1 > res1 {
            str1 = s[l1+1 : r1]
            res1 = tmp1
        }
        //        fmt.Printf("##str1=%s\n\n", str1)
    }

    //    even number
    for j := 0; j < n-1; j++ {
        tmp2 = 0
        l2 := j
        r2 := j + 1
        for {
            //            fmt.Println("##j=%d", j)
            if l2 >= 0 && r2 <= n-1 {
                //                fmt.Printf("l2=%d, r2=%d\n", l2, r2)
                //                fmt.Println("s[l2]=%v, s[r2]=%v", string(s[l2]), string(s[r2]))
                if s[l2] == s[r2] {
                    tmp2 += 2
                    l2--
                    r2++
                } else {
                    break
                }

            } else {
                break
            }
        }
        if tmp2 > res2 {
            str2 = s[l2+1 : r2]
            res2 = tmp2
        }
        //        fmt.Printf("##str2=%s\n\n", str2)
    }

    //    fmt.Printf("##res1=%d, res2=%d\n\n", res1, res2)
    if res2 > res1 {
        return str2
    }

    return str1
}

复杂度分析

  • 时间复杂度:O(n^2), 由于围绕中心来扩展回文会耗去 O(n) 的时间,所以总的复杂度为 O(n^2)。
  • 空间复杂度:O(1)。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值