欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > IT业 > 力扣516-最长回文子序列(Java详细题解)

力扣516-最长回文子序列(Java详细题解)

2024/10/25 19:31:56 来源:https://blog.csdn.net/2302_79761426/article/details/142456903  浏览:    关键词:力扣516-最长回文子序列(Java详细题解)

题目链接:力扣516-最长回文子序列

前情提要:

因为本人最近都来刷dp类的题目所以该题就默认用dp方法来做。

dp五部曲。

1.确定dp数组和i下标的含义。

2.确定递推公式。

3.dp初始化。

4.确定dp的遍历顺序。

5.如果没有ac打印dp数组 利于debug。

每一个dp题目如果都用这五步分析清楚,那么这道题就能解出来了。

题目思路:

如果你做过力扣647-回文子串或者看过我的那篇题解,那么做本题你会轻松不少。

本题题目要求找出s的最长回文子序列的长度。

注意这里的子序列可以不用连续。

话不多说直接开始我们的dp五部曲。

1.确定dp数组和i下标的含义。

该题的dp数组定义与力扣647相似,都要考虑回文串的性质。

所以dp[i] [j]定义的就是[i,j]范围内的最长回文子序列的长度。

2.确定递推公式。

在判断回文子串的题目中,关键逻辑就是看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]的同时加入 并不能增加[i,j]区间回文子序列的长度,那么分别加入s[i]、s[j]看看哪一个可以组成最长的回文子序列。

那我们要删除哪个元素呢,不是由我们决定,主要由递推公式决定。

在这里插入图片描述

dp[i] [j] = Math.max(dp[i - 1] [j],dp[i] [j - 1]);

3.dp初始化。

由递推公式可以看出dp[i] [j]是由dp[i + 1] [j - 1]推出。

注意这里的j一定是比i要大于等于的。所以他们递推的起点其实就是i = j的时候。

重点就在于i == j的时候,当i == j时就说明这一个元素的最长回文子序列就为他本身 那么 dp[i] [j] = 1;

4.确定dp的遍历顺序。

由递推公式可以看出dp[i] [j]是由dp[i + 1] [j - 1]推出。

在二维dp数组可以看出是由它的左下方推出,所以需要从下到上,从左到右遍历。

所以遍历顺序为:

for(int i = s.length() - 1;i >= 0;i --){for(int j = i + 1;j < s.length();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]);}}}

5.如果没有ac打印dp数组 利于debug。

在这里插入图片描述

class Solution {public int longestPalindromeSubseq(String s) {//dp的定义 在i到j的范围内的最长回文子序列的长度int [][] dp = new int [s.length() + 1][s.length() + 1];//递推公式 根据回文串的性质//如果下标为i和j的元素相同那么在i到j的范围内的最长回文子序列的长度就为i + 1到j - 1的范围内的最长回文子序列的长度 + 2//如果不相同 那么就可以删除下标i和j的任意一个元素  具体选择哪个 肯定要选择删除后获得更长的回文子序列//初始化//其实也可以由递推公式可以看出,每次都是由dp[i + 1][j - 1]推出。//重点就在于i == j的时候,当i == j时就说明这一个元素的最长回文子序列就为他本身 那么 dp[i][j] = 1;for(int i = 0;i < s.length();i ++){//在这里dp[i][i] 其实就是j = i的情况dp[i][i] = 1;}//遍历顺序 该题的递推是由dp[i + 1][j - 1]推出。//在二维dp数组中就是由它的左下方推出来,所以就要从下到上从左到右遍历for(int i = s.length() - 1;i >= 0;i --){for(int j = i + 1;j < s.length();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]);}}}//根据dp数组的定义 最后收集结果的地方就在于在0到s.length() - 1的范围内的最长回文子序列的长度 也就是整个字符串的最长回文子序列的长度return dp[0][s.length() - 1];}  
}

这一篇博客就到这了,如果你有什么疑问和想法可以打在评论区,或者私信我。

我很乐意为你解答。那么我们下篇再见!

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com