题目
leetcode 给你一个字符串 s,找到 s 中最长的 回文子串。
代码
package main
import "fmt"
func longestPalindrome(s string) string {
if len(s) == 0 || len(s) == 1 {
return s
}
start, end := 0, 1
for i := 0; i < len(s); i++ {
len1 := expend(s, i, i)
len2 := expend(s, i, i+1)
maxLen := max(len1, len2)
if maxLen > end-start {
start = i - (maxLen-1)/2
end = i + maxLen
}
}
return s[start:end]
}
func expend(s string, left int, right int) int {
for left >= 0 && right < len(s) && s[left] == s[right] {
left--
right++
}
return right - left - 1
}
func max(a int, b int) int {
if a > b {
return a
}
return b
}
func main() {
s := "babad"
fmt.Println(longestPalindrome(s))
}
解题思路
- 首先关于回文子串, 通用的解法就是以单字符和双字符分别向两边扩展, 分别找到最长的长度, 比较两者的最大值, 然后和全局的最大长度比较, 记录下全局的最大长度, 最后返回
- 本题的代码分析, 首先先判断特殊情况, 以免后面代码判断复杂
- 设定初始值, 即 start为0, end为1, 第一个字符肯定是回文子串
- 然后从头开始遍历, 看单字符和双字符扩展起来, 哪个得到的回文子串长就取哪个
- 难点1, expend的返回 right - left - 1, 这里返回回文子串的长度, 特别像这种表达式, 可以举个特例, 比如得到子串是 bab, 那么此时left是-1, right是3, 长度是3, 那么怎么返回3呢, 就是 3 - (-1) - 1, 这样就很容易得到表达式
- 难点2, longestPalindrome中根据长度和i得到start和end, 也是通过举个特例来得到表达式, 还是子串是 bab, 也就是maxLen是3, 此时i为1, 我们需要start为0, end为2, 怎么通过maxLen和i得到start和end呢, 简单的逻辑思考下, 就能得出 start = 1 - (3 - 1) / 2, 也就是 start = i - (maxLen-1)/2, 然后就更简单了, 直接 end = start + manLen 就行了
总结
回文子串都能通过单字符和双字符向两边扩展的方式解决, 技巧就是先处理特殊情况, 然后记录全局长度, 以及表达式的推导