leetcode 5.最长回文子串(golang)

41 阅读2分钟

5. 最长回文子串

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

如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。

示例 1:

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

示例 2:

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

提示:

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

解答:
解法一:动态规划
这道题使用动态规划算法能够减少算法的时间复杂度,我们首先初始化一个dp数组,用来存储动态规划的结果,双层for循环进行遍历,外层代表最长回文子串的长度,内层对每一个字符进行遍历,首先,l=0时表示每一个字符自身都是回文,l=1时,需要判断当前两个字符是否相同,l>=2时判断字符是否相同,相同则将dp数组更新,如果上次前一个位置的字符是回文,则此时也是回文,最后,更新最长回文字符串。

func longestPalindrome(s string) string {
    n := len(s)
    dp := make([][]bool, n)
    for i,_ := range dp {
        dp[i] = make([]bool, n)
    }
    ans := ""
    for l:=0; l<n; l++ { // l为本次循环遍历的子串长度
        for i:=0; i+l<n; i++ {
            j := i+l
            if l == 0 {
                dp[i][j] = true
            } else if l == 1 {
                dp[i][j] = (s[i] == s[j])
            } else {
                dp[i][j] = (s[i] == s[j] && dp[i+1][j-1])
            }
            if dp[i][j] && l+1 > len(ans) {
                ans = s[i:j+1]
            }
        }
    }
    return ans
}

解法二:中心扩展 中心扩展的思想是遍历每一个字符,计算以该字符为中心的最长回文串长度,定义一个compare函数用来计算最长回文串,由于有两种情况:"aba"式的回文,即s[i]!=s[i+1]和"abba"式的回文,即s[i]==s[i+1],所以要分两种情况调用两次compare,返回最长的子串。

unc longestPalindrome(s string) string {
	if s == "" {
		return ""
	}
	l, r := 0, 0
	maxlen := 0
	for i := 0; i < len(s); i++ {
		l1, r1 := compare(s, i, i+1)
		l2, r2 := compare(s, i, i)
		if r1-l1+1 > maxlen {
			maxlen = r1 - l1 + 1
			l = l1
			r = r1
		}
		if r2-l2+1 > maxlen {
			maxlen = r2 - l2 + 1
			l = l2
			r = r2
		}
	}
	return s[l : r+1]
}
func compare(s string, i int, j int) (int, int) {
	for i >= 0 && j < len(s) && s[i] == s[j] {
		i -= 1
		j += 1
	}
	return i + 1, j - 1
}