题目描述
LeetCode链接:最长回文子序列
给你一个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度。
子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。
思路
暴力递归和动态实现两种方法
递归变量,s[L…R]求该范围内最长回文子序列长度。
递归终止条件有两个:
- L 等于 R 时,返回1
- L 等于R-1 时,要判断s[L] 和 s[R] 是否相等,如果相等返回2,否则返回1【最大长度嘛,就取一个】。
递归判断条件也包含两个:
- s[L]和s[R] 不相等,三种情况继续递归
- p1 = self.process1(s, L+1, R-1)
- p2 = self.process1(s, L, R-1)
- p3 = self.process1(s, L+1, R)
- s[L]和s[R] 相等
- p4 = self.process1(s, L+1, R-1) + 2
然后取四个候选项中的最大值。
代码实现
class LongestPalindromeSubseq:
"""
最长回文子序列
https://leetcode.cn/problems/longest-palindromic-subsequence/
"""
def solution1(self, s: str) -> int:
"""
暴力递归
:param s:
:return:
"""
if not s:
return 0
return self.process1(s, 0, len(s)-1)
def process1(self, s, L, R):
"""
s[L..R]最长回文子序列长度返回
:param s:
:param L:
:param R:
:return:
"""
if L == R:
return 1
if L == R-1:
return 2 if s[L] == s[R] else 1
# s[L]和s[R] 不相等,三种情况继续递归
p1 = self.process1(s, L+1, R-1)
p2 = self.process1(s, L, R-1)
p3 = self.process1(s, L+1, R)
p4 = self.process1(s, L+1, R-1)+2 if s[L] == s[R] else 0
return max(p1, p2, p3, p4)
def solution2(self, s: str) -> int:
"""
动态规划
:param s:
:return:
"""
n = len(s)
dp = [[0]*n for _ in range(n)]
dp[n-1][n-1] = 1
for i in range(n-1):
dp[i][i] = 1
dp[i][i+1] = 2 if s[i] == s[i+1] else 1
for i in range(n-3, -1, -1):
for j in range(i+2, n):
dp[i][j] = max(dp[i][j-1], dp[i+1][j])
if s[i] == s[j]:
dp[i][j] = max(dp[i][j], 2+dp[i+1][j-1])
return dp[0][n-1]