leetcode 5 最长回文子串 - 输出子串

题目

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

如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。

示例

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

解析

这道题和之前的那道回文的很像:647回文子串,求个数,解法还是动态规划,用动规五部曲分析下:
1、确定DP数组及其含义
这道题的定义方法之前遇到过:表示区间范围[i,j] (注意是左闭右闭)的子串是否是回文子串,如果是dp[i][j]为true,否则为false。(是一个true还是false的定义,由于题目是求最长回文串,所以这个dp肯定不能用来当最后的结果)

2、确定递推公式
当s[i] != s[j] 时,那什么都不用说了,肯定是false;
当s[i] == s[j] 时,这就得分情况看下(和之前那道题的分情况套路一样):

  • 若i == j,那就意味是是同一个值,如"a",那没问题,是回文;
  • 若j - i = 1,那意味着是挨着的两个,如"aa",这样的也是回文,注意是j-i,j比i大;
  • 其余的情况,就需要看前一时刻的递推公式怎么样,即dp[i+1][j-1](注意是谁加谁减)

3、 初始化
二维布尔型dp数组的话,默认初始化是false,但要注意其实dp[i][i]这种的一定是true,可以在初始化的时候赋值好

4、遍历顺序
字符串类型的动规遍历顺序都一样,从左下角到右上角

func longestPalindrome(s string) string {
    n := len(s)
    maxLen := 0
    leftIndex := 0
    dp := make([][]bool, n+1)
    for i := 0; i <= n; i++ {
        dp[i] = make([]bool, n+1)
        dp[i][i] = true // 这一行加不加都行
    } 
    for i := n-1; i >= 0; i-- {
        for j := i; j <= n-1; j++ {
            if s[i] == s[j] {
                if j - i <= 1 || dp[i+1][j-1] == true {
                    dp[i][j] = true
                    if maxLen < j - i {
                        maxLen = j - i
                        leftIndex = i
                    }
                }
            }
        }
    }
    return s[leftIndex: leftIndex + maxLen + 1] // 这里要+1是语法特性,比如babad,取s[0:2]就是ba
}

另一种方法是中心扩展法(也不太好理解,还是用动态规划吧)

func longestPalindrome(s string) string {
    n := len(s)
    start, end := 0, 0
    for i := 0; i < n; i++ {
        left1, right1 := expend(s, i, i, n)
        left2, right2 := expend(s, i, i+1, n)
        if right1 - left1 > end - start{
            start, end = left1, right1
        }
        if right2 - left2 > end - start{
            start, end = left2, right2
        }
    }
    return s[start:end+1]
}

func expend(s string, i, j, n int) (int, int) {
    for i >= 0 && j < n && s[i] == s[j] {
        i-- //中心扩展
        j++
    }
    return i+1, j-1 // 这里的返回结果可以根据例子想一个
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值