時間:2020-6-21
題目地址:https://leetcode-cn.com/problems/longest-palindromic-substring/
題目難度:Medium
題目描述:
給定一個字符串 s,找到 s 中最長的迴文子串。你可以假設 s 的最大長度爲 1000。
示例 1:
輸入: "babad"
輸出: "bab"
注意: "aba" 也是一個有效答案。
示例 2:
輸入: "cbbd"
輸出: "bb"
思路1:暴力破解
代碼段1:45/103 超時 天呀
from collections import Counter
class Solution:
def longestPalindrome(self, s: str) -> str:
result = ""
a = Counter(list(s))
print(a)
for i, j in sorted(a.items(), key=lambda r:r[1], reverse=True):
temp, result_0= [], ""
for x, y in enumerate(s):
if y == i:
temp.append(x)
print(temp)
for p in temp:
for q in temp:
print(p)
print(q)
print(s[p:q + 1])
if(s[p:q + 1] == (s[p:q + 1])[::-1]):
result_0 = s[p:q + 1] if len(result_0) < (q + 1 - p ) else result_0
print(result_0)
print("=======")
print(result)
if not result or len(result) <= len(result_0):
result = result_0
print(result)
return result
總結:
- 今天提交了考試的資料,身體也不太舒服,明天繼續整吧
- 下邊的是別人的暴力,只有一個用例超時,優秀
class Solution:
# 暴力匹配(超時)
def longestPalindrome(self, s: str) -> str:
# 特判
size = len(s)
if size < 2:
return s
max_len = 1
res = s[0]
# 枚舉所有長度大於等於 2 的子串
for i in range(size - 1):
for j in range(i + 1, size):
if j - i + 1 > max_len and self.__valid(s, i, j):
max_len = j - i + 1
res = s[i:j + 1]
return res
def __valid(self, s, left, right):
# 驗證子串 s[left, right] 是否爲迴文串
while left < right:
if s[left] != s[right]:
return False
left += 1
right -= 1
return True
思路2:動態規劃
代碼段2:通過
class Solution:
def longestPalindrome(self, s: str) -> str:
size = len(s)
if size < 2:
return s
dp = [[False for _ in range(size)] for _ in range(size)]
max_len = 1
start = 0
for i in range(size):
dp[i][i] = True
for j in range(1, size):
for i in range(0, j):
if s[i] == s[j]:
if j - i < 3:
dp[i][j] = True
else:
dp[i][j] = dp[i + 1][j - 1]
else:
dp[i][j] = False
if dp[i][j]:
cur_len = j - i + 1
if cur_len > max_len:
max_len = cur_len
start = i
return s[start:start + max_len]
總結:
- 還是不行呀,動態規劃,簡直是噩夢
- 寫完代碼可以在紙上畫下表格,填上代碼運行的過程
思路3:中心擴散
代碼段3:通過
class Solution:
def longestPalindrome(self, s: str) -> str:
size = len(s)
if size < 2:
return s
# 至少是 1
max_len = 1
res = s[0]
for i in range(size):
palindrome_odd, odd_len = self.__center_spread(s, size, i, i)
palindrome_even, even_len = self.__center_spread(s, size, i, i + 1)
# 當前找到的最長迴文子串
cur_max_sub = palindrome_odd if odd_len >= even_len else palindrome_even
if len(cur_max_sub) > max_len:
max_len = len(cur_max_sub)
res = cur_max_sub
return res
def __center_spread(self, s, size, left, right):
"""
left = right 的時候,此時迴文中心是一個字符,迴文串的長度是奇數
right = left + 1 的時候,此時迴文中心是一個空隙,迴文串的長度是偶數
"""
i = left
j = right
while i >= 0 and j < size and s[i] == s[j]:
i -= 1
j += 1
return s[i + 1:j], j - i - 1
總結:
- 暴力是基礎,動態優化必須掌握,擴散中心得會寫,競賽級別的Manacher's Algorithm 馬拉車算法就算了,看着都頭疼