双11打卡力扣
Python版本的中心扩散法
class Solution:
# 寻找最长回文串,返回下标
def expandAroundCenter(self, s, left, right):
while left >= 0 and right < len(s) and s[left] == s[right]:
left -= 1
right += 1
return left + 1, right - 1 # 结束循环前left和right又执行了一遍循环体
def longestPalindrome(self, s: str) -> str:
start, end = 0, 0
for i in range(len(s)):
# 回文字符串长度为奇数的情况
left1, right1 = self.expandAroundCenter(s, i, i)
# 回文字符串长度为偶数的情况
left2, right2 = self.expandAroundCenter(s, i, i + 1)
# 判断是否找到更长的回文字符串
if right1 - left1 > end - start:
start, end = left1, right1
if right2 - left2 > end - start:
start, end = left2, right2
return s[start:end+1] # 注意字符串截取时的+1操作
下面是补作业时间
新增了Go版本的中心扩散法和动态规划
//动态规划版本
func longestPalindrome(s string) string {
n := len(s)
if n < 2 {
return s
}
maxLen := 1
begin := 0
// 动态创建二维数组,用make
dp := make([][]bool, n)
for i := 0; i < n; i++ {
// 动态创建一维数组
dp[i] = make([]bool, n)
//将对角线针对元素自身的dp[i][i]赋值true
dp[i][i] = true
}
// j表示子串长度从2-n
for j := 1; j < n+1; j++ {
// 枚举左边界
for i := 0; i < n; i++ {
// 子串长度j=k-i+1,即右边界k=j+i-1
k := j + i - 1
// 右边界如果越界的话直接跳出循环
if k >= n {
break
}
if s[i] != s[k] {
dp[i][k] = false
} else {
// 左右边界之间只存在1个或0个元素
if k-i < 3 {
dp[i][k] = true
} else {
dp[i][k] = dp[i+1][k-1]
}
}
// 最终判断当前子串长度是否唱过最大长度并且符合回文条件
if dp[i][k] && k-i+1 > maxLen {
maxLen = k - i + 1
begin = i
}
}
}
return s[begin : begin+maxLen]
}
//中心扩散法
func longestPalindrome(s string) string {
if len(s) == 0 {
return ""
} else if len(s) == 1 {
return s
}
start, end := 0, 0
for i := 0; i < len(s); i++ {
// 回文字符串的长度为奇数
left1, right1 := findTheLongest(s, i, i)
left2, right2 := findTheLongest(s, i, i+1)
if right1-left1 > end-start {
start, end = left1, right1
}
if right2-left2 > end-start {
start, end = left2, right2
}
}
return s[start : end+1]
}
论时间复杂度的话中心扩散法和动态规划都是O(n^2),但是整体性能还是中心扩散要快一点,空间发展的的话动态规划是O(n^2),而中心扩散法是O(1)。