作者: 负雪明烛
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. Django结合Echarts在前端展示数据

    前言 最近在用Django写UI自动化测试平台,基本快要弄完了,但是首页只有项目列表展示,一直感觉很空旷,所以想把一些关键数据在首页展示出来. 这时就想到利用Echarts这个开源项目,但是Djang ...

  2. javaSE高级篇1 — 异常与多线程基础

    1.异常的体系结构  注:Throwable是一个类,不是一个接口,这个类里面是描述的一些Error和Exception的共性,如图所示: 异常 / 错误是什么意思? 定义:指的是程序运行过程中,可能 ...

  3. 巩固java第四天

    巩固内容: HTML 元素 HTML 文档由 HTML 元素定义. HTML 元素 开始标签 * 元素内容 结束标签 * <p> 这是一个段落 </p> <a href= ...

  4. 12. Fedora 中文乱码问题

    1. Rhythmbox(音乐播放器乱码) yum install python-mutagen mid3iconv -e GBK *.mp3 2. totem电影播放机播放列表乱码解决1).修改to ...

  5. Redis6 新特性

    Redis6新特性 ACL安全策略 ACL(access control list): 访问控制列表,可以设置多个用户,并且给每个用户单独设置命令权限和数据权限 default用户和使用require ...

  6. linux vi(vim)常用命令汇总(转)

    前言 首先解析一个vim vi是unix/linux下极为普遍的一种文本编辑器,大部分机器上都有vi的各种变种,在不同的机器上常用不同的变种软件,其中vim比较好用也用的比较广泛.vim是Vi Imp ...

  7. ORACLE 数据块PCTFREE和PCTUSED

    PCTFREE表示一个数据块可用空间小于PCTFREE时,该数据块不在被记录在FREELIST中,即不能插入新数据. PCTUSED表示一个数据块已经用空间如果小于PCTUSED时,该数据块才会被重新 ...

  8. Oracle带输入输出参数的存储过程

    (一)使用输入参数 需求:在emp_copy中添加一条记录,empno为已有empno的最大值+1,ename不能为空且长度必须大于0,deptno为60. 创建存储过程: create or rep ...

  9. 解决 nginx: [error] invalid PID number "" in "/usr/local/nginx/logs/nginx.pid"

    使用/usr/local/nginx/sbin/nginx -s reload 重新读取配置文件出错 [root@localhost nginx]/usr/local/nginx/sbin/nginx ...

  10. sql优化的8种方式

    1.设置索引. MySQL索引操作:给表列创建索引: 建表时创建索引: create table t(id int,name varchar(20),index idx_name (name)); 给 ...