作者: 负雪明烛
id: fuxuemingzhu
个人博客: http://fuxuemingzhu.cn/


题目地址:https://leetcode.com/problems/longest-palindromic-subsequence/description/

题目描述

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

题目大意

找出一个字符串中最长的回文序列的长度。注意序列可以是不连续的,而子字符串是连续的。

解题思路

做完昨天的每日一题 446. 等差数列划分 II - 子序列 之后,相信大家对于子序列问题的套路已经更加了解了。子序列问题不能用滑动窗口了,可以用动态规划来解决。子序列问题的经典题目就是 300. 最长递增子序列,务必掌握。

先从整体思路说起。

子序列问题,由于是数组中的非连续的一个序列,使用动态规划求解时,避免不了二重循环:第一重循环是求解动态规划的每一个状态

d

p

[

i

]

,

(

0

<

=

i

<

=

N

)

dp[i], (0 <= i <= N)

dp[i],(0<=i<=N) ,第二重循环是向前寻找上一个子序列的结尾

j

,

(

0

<

=

j

<

i

)

j ,(0 <= j < i)

j,(0<=j<i)$ 来和

i

i

i 一起构成满足题意的新的子序列。

  • 对于「最长递增子序列」问题,我们对

    i

    ,

    j

    i, j

    i,j 的要求是

    n

    u

    m

    s

    [

    i

    ]

    >

    n

    u

    m

    s

    [

    j

    ]

    nums[i] > nums[j]

    nums[i]>nums[j],即递增;

  • 对于「能构成等差数列的子序列」问题,我们对

    i

    ,

    j

    i, j

    i,j 的要求是

    n

    u

    m

    [

    i

    ]

    num[i]

    num[i] 可以在

    n

    u

    m

    s

    [

    j

    ]

    nums[j]

    nums[j] 的基础上构成等差数列。

  • 对于「最长回文子序列」问题,我们对

    i

    ,

    j

    i, j

    i,j 本身的取值没有要求,但是希望能够成最长的回文子串。

在动态规划问题中,我们找到一个符合条件的

j

j

j ,然后就可以通过状态转移方程由

d

p

[

j

]

dp[j]

dp[j] 推导出

d

p

[

i

]

dp[i]

dp[i] 。

然后,我理一下本题的解法。

当已知一个序列是回文时,在其首尾添加元素后的序列存在两种情况:

  1. 首尾元素相等,则最长回文的长度 + 2;
  2. 首尾元素不相等,则最长回文序列长度为 仅添加首元素时的最长回文长度 与 仅添加尾元素时的最长回文长度 的最大值。

状态定义

d

p

[

i

]

[

j

]

dp[i][j]

dp[i][j] 表示

s

[

i

j

]

s[i…j]

s[i…j] 中的最长回文序列长度。

状态转移方程

  1. i

    >

    j

    i > j

    i>j,

    d

    p

    [

    i

    ]

    [

    j

    ]

    =

    0

    dp[i][j] = 0

    dp[i][j]=0;

  2. i

    =

    =

    j

    i == j

    i==j,

    d

    p

    [

    i

    ]

    [

    j

    ]

    =

    1

    dp[i][j] = 1

    dp[i][j]=1;

  3. i

    <

    j

    i < j

    i<j 且

    s

    [

    i

    ]

    =

    =

    s

    [

    j

    ]

    s[i] == s[j]

    s[i]==s[j],

    d

    p

    [

    i

    ]

    [

    j

    ]

    =

    d

    p

    [

    i

    +

    1

    ]

    [

    j

    1

    ]

    +

    2

    dp[i][j] = dp[i + 1][j - 1] + 2

    dp[i][j]=dp[i+1][j−1]+2;

  4. i

    <

    j

    i < j

    i<j 且

    s

    [

    i

    ]

    =

    s

    [

    j

    ]

    s[i]!= s[j]

    s[i]!=s[j],

    d

    p

    [

    i

    ]

    [

    j

    ]

    =

    m

    a

    x

    (

    d

    p

    [

    i

    +

    1

    ]

    [

    j

    ]

    d

    p

    [

    i

    ]

    [

    j

    1

    ]

    )

    dp[i][j] = max(dp[i + 1][j],dp[i][j - 1])

    dp[i][j]=max(dp[i+1][j],dp[i][j−1]);

遍历顺序
从状态转移方程可以看出,计算

d

p

[

i

]

[

j

]

dp[i][j]

dp[i][j] 时需要用到

d

p

[

i

+

1

]

[

j

1

]

dp[i+1][j - 1]

dp[i+1][j−1] 和

d

p

[

i

+

1

]

[

j

]

dp[i + 1][j]

dp[i+1][j],所以对于

i

i

i 的遍历应该从后向前;对于

j

j

j 的遍历应该从前向后。

返回结果
最后返回

d

p

[

0

]

[

s

.

l

e

n

g

t

h

(

)

1

]

dp[0][s.length() - 1]

dp[0][s.length()−1]。

代码

提供了三种语言的代码。

java 代码

class Solution {
public int longestPalindromeSubseq(String s) {
int size = s.length();
int[][] dp = new int[size][size];
for(int i = size - 1; i >= 0; i--){
dp[i][i] = 1;
for(int j = i + 1; j < size; j++){
if(s.charAt(i) == s.charAt(j)){
dp[i][j] = dp[i + 1][j - 1] + 2;
}else{
dp[i][j] = Math.max(dp[i + 1][j], dp[i][j - 1]);
}
}
}
return dp[0][size - 1];
}
}

C++代码:

class Solution {
public:
int longestPalindromeSubseq(string s) {
int size = s.size();
vector<vector<int>> dp(size, vector<int>(size, 0));
for(int i = size - 1; i >= 0; i--){
dp[i][i] = 1;
for(int j = i + 1; j < size; j++){
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][size - 1];
}
};

python 代码:

class Solution:
def longestPalindromeSubseq(self, s):
n = len(s)
dp = [[0] * n for _ in range(n)]
for i in range(n - 1, -1, -1):
dp[i][i] = 1
for j in range(i + 1, n):
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][n - 1]
  • 时间复杂度:

    O

    (

    N

    2

    )

    O(N^2)

    O(N2)

  • 空间复杂度:

    O

    (

    N

    2

    )

    O(N^2)

    O(N2)

刷题心得

子序列的动态规划解法:两重循环。其实就看对于每个

i

i

i,当找到满足题目要求的

j

j

j 的时候,状态转移方程怎么变化。

参考:http://blog.csdn.net/camellhf/article/details/70337501

日期

2018 年 3 月 15 日 --雾霾消散,春光明媚
2021 年 8 月 12 日——对面在装修,很吵

【LeetCode】516. Longest Palindromic Subsequence 最长回文子序列的更多相关文章

  1. [LeetCode] 516. Longest Palindromic Subsequence 最长回文子序列

    Given a string s, find the longest palindromic subsequence's length in s. You may assume that the ma ...

  2. 516 Longest Palindromic Subsequence 最长回文子序列

    给定一个字符串s,找到其中最长的回文子序列.可以假设s的最大长度为1000. 详见:https://leetcode.com/problems/longest-palindromic-subseque ...

  3. [LeetCode] Longest Palindromic Subsequence 最长回文子序列

    Given a string s, find the longest palindromic subsequence's length in s. You may assume that the ma ...

  4. Leetcode 5. Longest Palindromic Substring(最长回文子串, Manacher算法)

    Leetcode 5. Longest Palindromic Substring(最长回文子串, Manacher算法) Given a string s, find the longest pal ...

  5. [LeetCode] 5. Longest Palindromic Substring 最长回文子串

    Given a string s, find the longest palindromic substring in s. You may assume that the maximum lengt ...

  6. [leetcode]5. Longest Palindromic Substring最长回文子串

    Given a string s, find the longest palindromic substring in s. You may assume that the maximum lengt ...

  7. LN : leetcode 516 Longest Palindromic Subsequence

    lc 516 Longest Palindromic Subsequence 516 Longest Palindromic Subsequence Given a string s, find th ...

  8. 516. Longest Palindromic Subsequence最长的不连续回文串的长度

    [抄题]: Given a string s, find the longest palindromic subsequence's length in s. You may assume that ...

  9. [leetcode]516. Longest Palindromic Subsequence最大回文子序列

    Given a string s, find the longest palindromic subsequence's length in s. You may assume that the ma ...

随机推荐

  1. Git分布式版本控制系统基础

    查看创建的账号 下来在该当前的⽬录下创建⽂件,并且进⾏提交 使⽤git log就可以看到最近提交的⽇志记录的信息 查看窗户的状态信息 某些时候我们可能需要回退到之前的版本,那么具体处理的步骤为: 1. ...

  2. C语言中不用 + 和 - 求两个数之和

    (二)解题 题目大意:不用+或者-实现两个整数的加法 解题思路:不用+或者-,就自然想到位运算,无非就是与或非来实现二进制的加法 首先,我们来看一位二进制的加法和异或运算 A B A&B A^ ...

  3. Shell 统计文件的行数

    目录 统计文件的行数 题目 题解-awk 题解-wc 题解sed 统计文件的行数 题目 写一个 bash脚本以输出一个文本文件 nowcoder.txt中的行数 示例: 假设 nowcoder.txt ...

  4. Yarn 生产环境核心参数配置案例

    目录 Yarn 生产环境核心参数配置案例 需求 修改yarn-site.xml配置 分发 重启集群 执行WordCount程序 Yarn 生产环境核心参数配置案例 调整下列参数之前要拍摄Linux快照 ...

  5. Spark(十三)【SparkSQL自定义UDF/UDAF函数】

    目录 一.UDF(一进一出) 二.UDAF(多近一出) spark2.X 实现方式 案例 ①继承UserDefinedAggregateFunction,实现其中的方法 ②创建函数对象,注册函数,在s ...

  6. IDEA 超实用使用技巧分享

    前言 工欲善其事 ​ 必先利其器 最近受部门的邀请,给入职新人统一培训IDEA,发现有很多新人虽然日常开发使用的是IDEA,但是还是很多好用的技巧没有用到,只是用到一些基本的功能,蛮浪费IDEA这个优 ...

  7. [学习总结]1、View的scrollTo 和 scrollBy 方法使用说明和区别

    参考资料:http://blog.csdn.net/vipzjyno1/article/details/24577023 非常感谢这个兄弟! 先查看这2个方法的源码: scrollTo: 1 /** ...

  8. android知识点duplicateParentState

    android知识点duplicateParentState 今天要做一个效果,组件RelativeLayout上有两个TextView,这两个TextView具有不同的颜色值,现在要的效果是,当Re ...

  9. SpringIOC原理

    IOC(DI):其实这个Spring架构核心的概念没有这么复杂,更不像有些书上描述的那样晦涩.java程序员都知道:java程序中的每个业务逻辑至少需要两个或以上的对象来协作完成,通常,每个对象在使用 ...

  10. 实时数据同步inotify+rsync

    inotify inotify是一个实时监控服务,他能实时监控服务器中的目录的变化,发现目录中变化后,在配合rsync服务推送到备份服务器上 inotify要求内核要在2.6.13或之上,通过noti ...