来源:力扣(LeetCode)
链接:最长回文子串
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
问题描述
给你一个字符串 s,找到 s 中最长的回文子串。
示例
示例 1:
输入:s = “babad”
输出:“bab”
解释:“aba” 同样是符合题意的答案。
示例 2:
输入:s = “cbbd”
输出:“bb”
示例 3:
输入:s = “a”
输出:“a”
示例 4:
输入:s = “ac”
输出:“a”
代码
package main
import "fmt"
/*
方法一:暴力法,时间复杂度:O(N^3)
1. 遍历字符串
1.1 用后续的字符和当前字符比较:如果相等,则截取当前位置到相等字符位置的子字符串
1.2 判断截取的子字符串是不是回文字符串,如果是则保存到变量 circleStr,如果后续截取的子字符转也是回文字符串,则判断该回文字符串和 circleStr 的长度,
如果比 circleStr,则把该回文字符串赋值给 circleStr
2. 返回 circleStr
注意:输入字符串小于等于2时需要做特殊处理
*/
func longestPalindrome1(s string) string {
circleStr := s[:1]
if len(s) <= 1 {
return s
}
if len(s) == 2 {
if s[0] == s[1] {
return s
}else {
return s[:1]
}
}
for idx1, val1 := range s {
for idx2, val2 := range s[idx1+1:] {
if val1 == val2 {
tempStr := s[idx1: idx1+2+idx2]
// 判断是否是回文字符串
if IsCircleStr(tempStr) {
if len(tempStr) > len(circleStr) {
circleStr = tempStr
}
}
}
}
}
return circleStr
}
func IsCircleStr(s string) bool {
isCircle := true
for i := 0; i < len(s)/2; i++ {
if s[i] != s[len(s) - i - 1] {
isCircle = false
break
}
}
return isCircle
}
/*
方法二:中心扩散法,时间复杂度:O(N^2)
1. 枚举所有元素的位置
2. 从枚举的位置向两边扩散,直到不能扩散为止,记录此时的回文子串
3. 对比当前的回文子串和记录的回文子串,保留较大者
注意:
奇数回文子串(bab)和偶数回文子串(abba),要分别做处理
*/
func longestPalindrome2(s string) string {
circleStr := ""
tempStr := ""
for idx, _ := range s { // 枚举所有元素的位置
// 1. 从枚举的位置向两边扩散,直到不能扩散为止
left1, right1 := ExpandAroundCenter(s, idx, idx) // 奇数回文子串
left2, right2 := ExpandAroundCenter(s, idx, idx+1) // 偶数回文子串
// 2. 记录此时的回文子串
if (right1 - left1) > (right2 - left2) {
tempStr = s[left1: right1+1]
} else {
tempStr = s[left2: right2+1]
}
// 3. 对比当前的回文子串和记录的回文子串,保留较大者
if len(tempStr) > len(circleStr) {
circleStr = tempStr
}
}
return circleStr
}
func ExpandAroundCenter(s string, left, right int) (int, int) {
for {
if (left >= 0 && right <= len(s)-1) && (s[left] == s[right]) {
left--
right++
}else {
break
}
}
// 循环退出时,left比我们要的左索引小1,right比我们想要的右索引大1
return left+1, right-1
}
/*
方法三:动态规划,时间复杂度:O(N^2)
动态规划利用了回文字符串的性质:去除两边的字符仍然是回文子串
*/
func longestPalindrome3(s string, left int, right int) string {
ret := ""
if right - left <= 2 {
ret = s
}else {
if s[left] == s[right] {
left ++
right--
ret = longestPalindrome3(s[left:right], left, right)
}
}
return ret
}
// 好吧,动态规划真的好难,每次遇到动态规划都跪
func main() {
s1 := "babad"
s01 := longestPalindrome2(s1)
fmt.Println(s01)
s2 := "bb"
s02 := longestPalindrome2(s2)
fmt.Println(s02)
s3 := "a"
s03 := longestPalindrome2(s3)
fmt.Println(s03)
s4 := "ac"
s04 := longestPalindrome2(s4)
fmt.Println(s04)
s5 := "abcda"
s05 := longestPalindrome2(s5)
fmt.Println(s05)
}