Q5_最长回文子串

来源:力扣(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)
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值