leetcode 516 Longest Palindromic Subsequence

leetcode 516 Longest Palindromic Subsequence

先看一下题目原文:

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”.

这里对于题目的认识,最长公共子串(Longest Common Substring)与最长公共子序列(Longest Common Subsequence)的区别: 子串要求在原字符串中是连续的,而子序列则只需保持相对顺序,并不要求连续。

这道题考察的是动态规划类型的算法,也就是DP(Dynamic Programming)问题,如果一个问题的每次决策依赖于当前的状态的时候,并且当前的状态又会引起下一次的状态转移,则可以用动态规划问题来解决这个问题。

对于这个题来讲,最长的子串我们默认为与母串等长也就是长度为n,那么他的始终端点假设[i,j],此时根据s[i]和s[j]的状态,分成两种情况,第一是相等,则等于n-2长度的字符串的最长子串 +2, 不相等的情况下,等于n-1长度的字符串的最长子串,那这里n-1的字符串有两种情况,所以用一个max()来得出结果。此处参考花花酱的示意图:
花花酱的两个思路
示意图的左边是一个伪代码段,这里在我的代码注释中解释了,每次遍历的数值原因,这里双循环所以时间复杂度是O(n^2),两维列表,空间复杂度也是一样的。

def longestPalindromeSubseq(self, s: str) -> int:
    l = len(s)
    if l == 0: return 0
    if l == 1: return 1
    #定义储存答案的字典
    #初始化填充
    #因为answer的下标是从i到j所以创建一个i*j最大取值范围的矩阵
    #且对角线上的值是1 因为i==j的时候是奇数 可以作为一个长度
    ans = [[0]*l for _ in range(l)]
    for n in range(l):
        ans[n][n] = 1
    #i最大是l-1 j最大也是l-1
    #length指的是子序列的长度,是从1到全长,如果用range记得最后一个+1
    for length in range(2,l+1):
        #i是这个sub string 的左下标 j 是右下标
        #i的取值范围就是在1到 (序列全长 - 子序列总长),在range里就是(0,l-length+1)
        #例如全长5 总长3 【12345】那么 最后一个序列就是 【345】 那么i的最后一个值就是下标2 -> 5-3
        for i in range(l-length+1):
            #j的取值范围就是在 i+总长-1
            j = i+length-1
            if s[i]==s[j]:
                #如果左右相等 那么这个最长回文长度就等于去掉左右两端的子串的最长长度+2
                ans[i][j] = ans[i+1][j-1]+2
            else:
                #如果左右不等,那么这个解就是分解成去头或者去尾的最大的那个
                ans[i][j] = max(ans[i+1][j],ans[i][j-1])
    return ans[0][l-1]

以后补充一个优化速度和空间复杂度的办法。
当然DP问题也会有递归遍历的解法,同样的问题,普遍递归要慢于迭代循环。后期可以补充一个递归的方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值