难度: Medium
原题连接
内容描述
Given a string s, find the longest palindromic subsequence's length in s. You may assume that the maximum length of s is 1000.
Example 1:
Input:
"bbbab"
Output:
4
One possible longest palindromic subsequence is "bbbb".
Example 2:
Input:
"cbbd"
Output:
2
One possible longest palindromic subsequence is "bb".
思路 1 - 时间复杂度: O(N^2)- 空间复杂度: O(N^2)******
其实就是求s和s[::-1]的最长公共子序列
beats 49.81%
class Solution:
def longestPalindromeSubseq(self, s):
"""
:type s: str
:rtype: int
"""
if s == s[::-1]:
return len(s)
return self.longestCommonSubsequence(s, s[::-1])
def longestCommonSubsequence(self, s1, s2): # O(mn)
m, n = len(s1), len(s2)
dp = [[0] * (n + 1) for i in range(m + 1)]
for i in range(1, m + 1):
for j in range(1, n + 1):
if s1[i - 1] == s2[j - 1]:
dp[i][j] = dp[i - 1][j - 1] + 1
else:
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
return dp[-1][-1]
思路 2 - 时间复杂度: O(N^2)- 空间复杂度: O(N^2)******
记忆化搜索,Top down,beats 5.99%,有的时候又会超时过不了,奇怪
python2死都AC不了,python3偶尔能AC
class Solution(object):
def longestPalindromeSubseq(self, s):
"""
:type s: str
:rtype: int
"""
cache = {}
def helper(s, i, j):
if (i, j) in cache:
return cache[(i,j)]
if i > j:
return 0
elif i == j:
return 1
else:
if s[i] == s[j]:
cache[(i,j)] = helper(s, i+1, j-1) + 2
else:
cache[(i,j)] = max(helper(s, i, j-1), helper(s, i+1, j))
return cache[(i,j)]
return helper(s, 0, len(s)-1)
思路 3 - 时间复杂度: O(N^2)- 空间复杂度: O(N^2)******
改进版记忆化搜索,beats 94.01%
class Solution:
def longestPalindromeSubseq(self, s):
"""
:type s: str
:rtype: int
"""
if s == s[::-1]:
return len(s)
cache = {}
def helper(s):
if s not in cache:
max_len = 0
for c in set(s):
i, j = s.find(c), s.rfind(c)
max_len = max(max_len, 1 if i == j else 2 + helper(s[i+1:j]))
cache[s] = max_len
return cache[s]
return helper(s)
思路 4 - 时间复杂度: O(N^2)- 空间复杂度: O(N^2)******
Bottom up
DP, beats 92.51%
class Solution:
def longestPalindromeSubseq(self, s):
"""
:type s: str
:rtype: int
"""
if s == s[::-1]:
return len(s)
dp = [[0]*len(s) for i in range(len(s))]
for i in range(len(s)):
dp[i][i] = 1
for j in range(1, len(s)):
for i in range(j-1, -1, -1):
if s[i] == s[j]:
dp[i][j] = dp[i+1][j-1] + 2
else:
dp[i][j] = max(dp[i+1][j], dp[i][j-1])
return dp[0][-1]
思路 5 - 时间复杂度: O(N^2)- 空间复杂度: O(N)******
dp[i] : longest palindrom subsequence start from i
这里的空间优化我确实没怎么看懂,希望有看懂的可以给我留言
beats 94.01%
class Solution:
def longestPalindromeSubseq(self, s):
"""
:type s: str
:rtype: int
"""
if s == s[::-1]:
return len(s)
dp = [1] * len(s)
for i in range(1, len(s)):
length = 0
for j in range(i-1, -1, -1):
tmp = dp[j]
if s[j] == s[i]:
dp[j] = length + 2
length = max(length, tmp)
return max(dp)
思路 6 - 时间复杂度: O(N^2)- 空间复杂度: O(N^2)******
参考A typical way to solve palindrome problems
beats 88.76%
class Solution:
def longestPalindromeSubseq(self, s):
"""
:type s: str
:rtype: int
"""
if not s or len(s) == 0:
return 0
if s == s[::-1]:
return len(s)
dp = [[0] * len(s) for i in range(len(s))]
for i in range(len(s)):
dp[i][i] = 1
for i in range(len(s)-1):
if s[i] == s[i+1]:
dp[i][i+1] = 2
else:
dp[i][i+1] = 1
for gap in range(2, len(s)):
for i in range(len(s)-gap):
j = i + gap
if s[i] == s[j]:
dp[i][j] = dp[i+1][j-1] + 2
else:
dp[i][j] = max(dp[i+1][j], dp[i][j-1])
return dp[0][-1]