leetcode 5 最长回文子串
给定一个字符串 s
,找到 s
中最长的回文子串。你可以假设 s
的最大长度为 1000。
示例 1:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
示例 2:
输入: "cbbd"
输出: "bb"
思路:
动态规划
为了改进暴力法,我们首先观察如何避免在验证回文时进行不必要的重复计算。考虑
我们给出
因此,
基本示例如下:
这产生了一个直观的动态规划解法,我们首先初始化一字母和二字母的回文,然后找到所有三字母回文,并依此类推…
复杂度分析
- 时间复杂度:O(n^2)O(n2),这里给出我们的运行时间复杂度为 O(n^2)O(n2) 。
- 空间复杂度:O(n^2)O(n2),该方法使用 O(n^2)O(n2) 的空间来存储表。
具体写码的时候用一个变量(代码中的sub)来记录目前最长的子串长度,用一个list(代码中的max_len)来记录最长子串的坐标
另一个leetcode上速度比较快的算法有点类似滑动窗口法,维护一个最大长度为lenth的窗口,并使用python语法糖q == q[::-1]来判断是否是回文字符串,但是要注意的是维护窗口时要同时维护奇数和偶数两种窗口。
答案:
class Solution(object):
def longestPalindrome(self, s):
"""
:type s: str
:rtype: str
"""
n = len(s)
if n == 0:
return ''
if n == 1:
return s
res = [[0 for _ in range(n)] for _ in range(n)]
sub = 1
max_len = [0,0]
for i in range(n):
res[i][i] = 1
if i != n-1 and s[i] == s[i+1]:
res[i][i+1] = 1
sub = 2
max_len=[i,i+1]
for i in range(n):
for j in range(1,min(i,n-i)+1):
if i-j>=0 and i+j<n and res[i-j+1][i+j-1] and s[i-j]==s[i+j]:
res[i-j][i+j] =1
#print 1+2*j
if sub<1+2*j:
sub = 1+2*j
max_len = [i-j,i+j]
#print sub,max_len
if i-j>=0 and i+1+j<n and res[i-j+1][i+j] and s[i-j] == s[i+j+1]:
res[i-j][i+j+1] =1
if sub<2+2*j:
sub = 1+2*j
max_len = [i-j,i+j+1]
#print sub,max_len
return s[max_len[0]:(max_len[1]+1)]
class Solution(object):
def longestPalindrome(self, s):
"""
:type s: str
:rtype: str
"""
if len(s) == 1 or s == s[::-1]:
return s
start = 0
length = 1
for i in range(len(s)):
p = s[i-length-1:i+1]
q = s[i-length:i+1]
if i-length-1 >= 0 and p == p[::-1]:
start = i-length-1
length += 2
if i-length >=0 and q == q[::-1]:
start = i - length
length += 1
return s[start:start+length]
[647] 回文子串
给定一个字符串,你的任务是计算这个字符串中有多少个回文子串。
具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被计为是不同的子串。
示例 1:
输入: "abc"
输出: 3
解释: 三个回文子串: "a", "b", "c".
示例 2:
输入: "aaa"
输出: 6
说明: 6个回文子串: "a", "a", "a", "aa", "aa", "aaa".
注意:
输入的字符串长度不会超过1000。
思路:
这道题的动态规划思路跟上一道题(第五题)完全一样,只不过在具体代码的时候,使用一个变量来记录回文子串的个数。
[516] 最长回文子序列
给定一个字符串s,找到其中最长的回文子序列。可以假设s的最大长度为1000。
示例 1:
输入:
"bbbab"
输出:
4
一个可能的最长回文子序列为 "bbbb"。
示例 2:
输入:
"cbbd"
输出:
2
一个可能的最长回文子序列为 "bb"。
思路:
这道题跟上两道题的动态规划思路完全不一样,首先,这道题寻找的是最长回文子序列,子序列可以不相连。其次,这道题要返回的是最长回文子序列的长度,不关心子序列,所以构造动态规划数组时也稍有不同。具体来说:
引入
递推公式可以表示为:
注意在具体代码的时候,循环应该是先判断间隔距离为1的所有字符对,然后依次增加。
答案:
class Solution(object):
def longestPalindromeSubseq(self, s):
"""
:type s: str
:rtype: int
"""
n = len(s)
if n<=1:
return n
if n==2:
if s[0]==s[1]:
return 2
else:
return 1
resgrid = [[0 for _ in range(n)] for _ in range(n)]
for i in range(n):
resgrid[i][i]=1
for gap in range(1,n):
for i in range(n):
if i+gap>=n:
break
l = i
h = i+gap
if s[l]==s[h]:
resgrid[l][h] = resgrid[l+1][h-1]+2
else:
resgrid[l][h]=max(resgrid[l+1][h],resgrid[l][h-1])
return resgrid[0][n-1]