【leetcode-Python】- Dynamic programming-516. Longest Palindromic Subsequence

题目链接

https://leetcode.com/problems/longest-palindromic-subsequence/

题目描述

给定字符串s,找出其中最长的回文子序列,并返回该序列的长度。s的最大长度为1000。

示例

输入:"bbbab"

输出:4

最长回文子序列为“bbbb”

解题思路

子序列为不连续的序列,最长子序列问题常用动态规划求解。

在最长回文子序列中,定义dp数组:dp[i][j]表示子串s[i,...j](闭区间)中的最长回文子序列的长度。在动态规划中要根据较小区间范围下的结果推出较大区间范围下的结果,dp[i][j]的更新和dp[i+1][j-1]有关。

设已知dp[i+1][j-1],即子串s[i+1,...j-1](闭区间)中的最长回文子序列的长度。如果s[i]==s[j],那么s[i]和s[j]也可以加入到已知的回文子序列中。因此有dp[i][j] = dp[i+1][j-1] + 2。

如果s[i]!=s[j],那么s[i]和s[j]一定不会同时出现在s[i,...j](闭区间)的最长回文子序列中。那么s[i,...j]的最长回文子序列长度要么等于s[i+1,...j]的最长回文子序列长度,要么等于s[i,...j-1]的最长回文子序列长度,即将s[i]和s[j]分别加入子串s[i+1,...j-1]中,看哪个子串范围内的最长回文子序列更长。因此有dp[i][j]  = max(dp[i+1][j],dp[i][j-1])。

base case为i=j时,dp[i][j] =1。i>j 时子序列不存在,因此dp[i][j] = 0。

由于计算dp[i][j]需要用到dp[i+1][j-1](左下角)、dp[i][j-1](左边)和dp[i-1][j](上边)的元素,因此对于二维数组dp,更新方式为从下向上,从左向右。

Python实现

class Solution:
    def longestPalindromeSubseq(self, s: str) -> int:
        dp = [[0 for _ in range(len(s))] for _ in range(len(s))]
        for i in range(len(s)):
            dp[i][i] = 1#j = i时,最长回文子序列长度为1
        for i in range(len(s)-1,-1,-1): #从下往上更新
            for j in range(i+1,len(s)):#从左往右更新,仅更新j>i的部分
                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][len(s)-1]
        

时间复杂度与空间复杂度

时间复杂度为O(N^2),空间复杂度为O(N^2)。

参考

https://labuladong.gitbook.io/algo/dong-tai-gui-hua-xi-lie/zi-xu-lie-lei-xing-wen-ti/zi-xu-lie-wen-ti-mo-ban

 

参考

https://leetcode.com/problems/longest-palindromic-subsequence/

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值