leetcode_长回文子串

72 阅读1分钟

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

示例 1:

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

示例 2:

输入: s = "cbbd"
输出: "bb"

提示:

  • 1 <= s.length <= 1000
  • s 仅由数字和英文字母组成

解法一、暴力解法

先求出所有的子串,然后判断每个子串是否是回文子串

func longestPalindrome(s string) string {
    var ret string
    for i := 0; i < len(s); i++ {
       for j := i + 1; j <= len(s); j++ {
          temp := s[i:j]
          if isValid(temp) && len(temp) > len(ret) {
             ret = temp
          }
       }
    }
    return ret
}

func isValid(s string) bool {
   length := len(s)
   for i := 0; i < length/2; i++ {
      if s[i] != s[length-i-1] {
         return false
      }
   }
   return true
}

解法二、利用上一次的结果

image.png

所以如果我们想知道 P(i,j)P(i,j)的情况,不需要调用判断回文串的函数了,只需要知道 P(i + 1,j - 1)P(i+1,j−1)的情况就可以了,这样时间复杂度就少了 O(n)O(n)。因此我们可以用动态规划的方法,空间换时间,把已经求出的 P(i,j)P(i,j)存储起来。

image.png

求 长度为 11 和长度为 22 的 P(i,j)P(i,j) 时不能用上边的公式,因为我们代入公式后会遇到 P[i][j]P[i][j] 中 i > j 的情况,比如求 P[1][2]P[1][2] 的话,我们需要知道 P[1+1][2-1]=P[2][1]P[1+1][2−1]=P[2][1] ,而 P[2][1]P[2][1] 代表着 S[2,1]S[2,1] 是不是回文串,显然是不对的,所以我们需要单独判断。

func longestPalindrome(s string) string {
   var preResult = make(map[int]map[int]bool)
   for i := 0; i < len(s); i++ {
      preResult[i] = make(map[int]bool)
   }
   var ret string
   
   // 求出每个长度的字符串是否是回文字符串 从小长度开始求 之后就能求出比它长的字符串是否是回文串
   for subLength := 1; subLength <= len(s); subLength++ {
      for start := 0; start < len(s); start++ {
         end := subLength + start - 1
         if end >= len(s) {
            break
         }
         preResult[start][end] = s[start] == s[end] && (preResult[start+1][end-1] || subLength == 1 || subLength == 2)
         if preResult[start][end] && subLength > len(ret) {
            ret = s[start : end+1]
         }
      }
   }
   return ret
}