[LeetCode-Golang] 5. 最长回文子串
题目
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例 1:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
示例 2:
输入: "cbbd"
输出: "bb"
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-palindromic-substring
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路
长度为奇数的回文串以中间元素为对称轴,长度为偶数的回文串以两个中间元素的中心为对称轴.
使用动态规划来做,
1.定义状态,二维数组dp[i][j]
表示子串 s[i, j]
是否为回文子串。
2.状态转移方程 dp[i][j] = (s[i] == s[j]) and dp[i + 1][j - 1]
3.边界条件
3.1 dp[i][i] = true(由此扩展奇数长度的回文子串)
3.2 dp[i][i+1] = s[i] == s[i+1](由此扩展偶数长度的回文子串)
4.当dp[i][j] = true时,更新maxStart = i,maxLen = j-i+1
复杂度分析
时间复杂度O(n2)
空间复杂度O(n2)
代码
func longestPalindrome(s string) string {
if len(s) <= 1 {
return s
}
// 最长回文子串起始位置和长度
maxStart,maxLen :=0, 1
// 动态规划二维数组dp[i][j]表示区间[i,j]的子串是否为回文子串,默认为false
sLen := len(s)
dp := make([][]bool,sLen)
for i := range dp {
dp[i] = make([]bool, sLen)
}
for i := 0; i < sLen-1; i++ {
// 单个元素构成的子串是回文串
dp[i][i] = true
// 相同的两个元素构成的字串是回文串
if s[i] == s[i+1] {
dp[i][i+1] = true
// 更新maxLen的值
maxLen = 2
maxStart = i
}
}
dp[sLen-1][sLen-1] = true
// 寻找长度>2的回文字串
for l := 3; l <= sLen && maxLen >= l-2; l++ {
for start := 0; start <= sLen - l; start++ {
end := start + l -1
if s[start] == s[end] && dp[start+1][end-1] == true{
maxLen = l
maxStart = start
dp[start][end] = true
}
}
}
return s[maxStart:maxStart+maxLen]
}