最长回文子序列 -- 动规

题目描述

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]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NLP_wendi

谢谢您的支持。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值