时间: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 马拉车算法就算了,看着都头疼
【2021-3-2】
思路4:双指针
分解问题:
- 寻找回文子串,从中间向两边扩散,需要考虑长度为奇偶
- 遍历字符串,不断更新最长的回文子串
代码段4:通过
class Solution:
def longestPalindrome(self, s: str) -> str:
res = ''
def palindrome(s, l, r):
while l >= 0 and r < len(s) and s[l] == s[r]:
l -= 1
r += 1
return s[l+1:r]
for i in range(len(s)):
s1 = palindrome(s, i, i)
s2 = palindrome(s, i, i+1)
res = s1 if len(res) < len(s1) else res
res = s2 if len(res) < len(s2) else res
return res
总结:
- 仿佛找到了刷算法的乐趣,就得有一些套路熟记于心。
- 优雅的很
2021-3-30
来自牛客
# -*- coding:utf-8 -*-
class Solution:
def getLongestPalindrome(self, A, n):
def ishuiwen(a_str, l, r):
while l >= 0 and r < len(a_str) and a_str[l] == a_str[r]:
l -= 1
r += 1
return a_str[l+1:r]
res = 0
for i in range(n):
huiwen1 = ishuiwen(A, i, i)
huiwen2 = ishuiwen(A, i, i+1)
res = max(res, len(huiwen1), len(huiwen2))
return res