给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:
输入: s = "babad"
输出: "bab"
解释: "aba" 同样是符合题意的答案。
示例 2:
输入: s = "cbbd"
输出: "bb"
提示:
1 <= s.length <= 1000s仅由数字和英文字母组成
解法一、暴力解法
先求出所有的子串,然后判断每个子串是否是回文子串
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
}
解法二、利用上一次的结果
所以如果我们想知道 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)存储起来。
求 长度为 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
}