[LeetCode-Golang] 5. 最长回文子串

题目

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

示例 1:

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

示例 2:

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-palindromic-substring
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

 

解题思路

长度为奇数的回文串以中间元素为对称轴,长度为偶数的回文串以两个中间元素的中心为对称轴.
使用动态规划来做,
1.定义状态,二维数组dp[i][j] 表示子串 s[i, j] 是否为回文子串。
2.状态转移方程 dp[i][j] = (s[i] == s[j]) and dp[i + 1][j - 1]
3.边界条件
  3.1 dp[i][i] = true(由此扩展奇数长度的回文子串)
  3.2 dp[i][i+1] = s[i] == s[i+1](由此扩展偶数长度的回文子串)
4.当dp[i][j] = true时,更新maxStart = i,maxLen = j-i+1

复杂度分析

时间复杂度O(n2)

空间复杂度O(n2)

代码

func longestPalindrome(s string) string {
    if len(s) <= 1 {
        return s
    }
    // 最长回文子串起始位置和长度
   maxStart,maxLen :=0, 1
    // 动态规划二维数组dp[i][j]表示区间[i,j]的子串是否为回文子串,默认为false
    sLen := len(s)
    
    dp := make([][]bool,sLen)
    for i := range dp {
        dp[i] = make([]bool, sLen)
    }
    for i := 0; i < sLen-1; i++ {
        // 单个元素构成的子串是回文串
        dp[i][i] = true
        // 相同的两个元素构成的字串是回文串
        if s[i] == s[i+1] {
            dp[i][i+1] = true
            // 更新maxLen的值
            maxLen = 2
            maxStart = i
        }
    }
    dp[sLen-1][sLen-1] = true
    // 寻找长度>2的回文字串
    for l := 3; l <= sLen && maxLen >= l-2; l++ {
        for start := 0; start <= sLen - l; start++ {
            end := start + l -1
            if s[start] == s[end] && dp[start+1][end-1] == true{
                maxLen = l
                maxStart = start
                dp[start][end] = true
            }
        }
    } 
    return s[maxStart:maxStart+maxLen]
}

 

posted @ 2020-03-15 23:11  世界边境  阅读(299)  评论(0编辑  收藏  举报