链接:https://leetcode-cn.com/problems/longest-palindromic-substring/
题目描述:给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
示例 2:
输入:s = "cbbd"
输出:"bb"
1 枚举解法
时间复杂度 O(n^3) 空间复杂度 O(1)
class Solution_brute_force:
"""
暴力枚举解法 时间O(n^3) 空间O(1)
"""
def longestPalindrome(self, s: str) -> str:
"""
:param s: input str
:return: the longest palindromic substring
"""
if s is None:
return None
for length in range(len(s), 0, -1): # 按长度从大到小遍历
for start in range(len(s) - length + 1):
if self.is_palindrome(s, start, start + length - 1):
return s[start: start + length]
return ""
def is_palindrome(self, s: str, left, right):
while left < right and s[left] == s[right]:
left += 1
right -= 1
return left >= right
2 中心线枚举解法
时间复杂度 O(n^2) 空间复杂度 O(1)
class Solution_centerline_enumerate:
"""
中心线枚举解法 时间O(n^2) 空间O(1)
"""
def longestPalindrome(self, s: str) -> str:
"""
:param s: input string
:return: the longest palindromic substring
"""
if s is None:
return None
answer = (0, 0)
for i in range(len(s)):
answer = max(answer, self.get_palindromic_from(s, i, i)) # 奇数子串
answer = max(answer, self.get_palindromic_from(s, i, i + 1)) # 偶数子串
return s[answer[1]: answer[0] + answer[1]]
def get_palindromic_from(self, s: str, left, right):
while left >= 0 and right < len(s) and s[left] == s[right]:
left -= 1
right += 1
return right - left - 1, left + 1
3 动态规划解法
时间复杂度 O(n^2),空间复杂度 O(n^2)
class Solution_dp:
"""
标准动态规划解法 时间O(n^2) 空间O(n^2)
"""
def longestPalindrome(self, s: str) -> str:
"""
:param s: input string
:return: the longest palindromic substring
"""
if not s: # 等价于 s is None or s == ''
return ''
if len(s) < 2:
return s
dp = [[False] * len(s) for _ in range(len(s))]
for i in range(len(s)):
dp[i][i] = True
# 状态转移方程
# if dp[i+1][j-1] == 1 and s[i] == s[j]
# dp[i][j] = 1
# else
# dp[i][j] = 0
answer = (0, 0)
for i in range(len(s) - 1, -1, -1): # dp[i][j]依赖于dp[i+1][j-1], i反向计算
for j in range(len(s)): # j的计算正反皆可
if i + 1 <= j - 1 and dp[i + 1][j - 1] and s[i] == s[j]:
dp[i][j] = True
elif i + 1 > j - 1 and s[i] == s[j]: # i与j相邻的情况,如s[i:j] = 'aa'
dp[i][j] = True
if dp[i][j]:
answer = max(answer, (j - i + 1, i))
return s[answer[1]:answer[0] + answer[1]]
4 dp滚动数组解法
时间复杂度 O(n^2),空间复杂度 O(n)
class Solution_dp_scrolling_arr:
"""
dp滚动数组解法 时间O(n^2) 空间O(n)
"""
def longestPalindrome(self, s: str) -> str:
"""
:param s: input string
:return: the longest palindromic substring
"""
if not s: # 等价于 s is None or s == ''
return ''
if len(s) < 2:
return s
dp = [[False] * len(s) for _ in range(2)]
# 状态转移方程
# if dp[i+1][j-1] == 1 and s[i] == s[j]
# dp[i][j] = 1
# else
# dp[i][j] = 0
answer = (0, 0)
for i in range(len(s) - 1, -1, -1): # dp[i][j]依赖于dp[i+1][j-1], i反向计算
for j in range(len(s)): # j的计算正反皆可
arr_idx = i % 2
if i == j or (i == j - 1 and s[i] == s[j]): # i与j相邻的情况,如s[i:j] = 'aa'
dp[arr_idx][j] = True
elif dp[(i + 1) % 2][j - 1] and s[i] == s[j]:
dp[arr_idx][j] = True
else: # 重置为false
dp[arr_idx][j] = False
if dp[arr_idx][j]:
answer = max(answer, (j - i + 1, i))
return s[answer[1]:answer[0] + answer[1]]