编程语言
首页 > 编程语言> > LeetCode——516. 最长回文子序列(Java)

LeetCode——516. 最长回文子序列(Java)

作者:互联网

题目描述

题干:
给你一个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度。
子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。

示例 1:
输入:s = "bbbab"
输出:4
解释:一个可能的最长回文子序列为 "bbbb" 。

示例 2:
输入:s = "cbbd"
输出:2
解释:一个可能的最长回文子序列为 "bb" 。

题解思路

返回最长的回文子序列的长度,这里的原字符串是不允许改变顺序的,但是子序列可以删除部分元素

这道题首先想到的是双指针,但是如何挑选指针移动标准上犯难,因为你不知道到底删选哪一个元素才能保证最长

所以我们采用动态规划的方法,从中间最短的只有一个元素开始,但是这里还是挺难理解的

这里的虽然看起来用到了二维数组,但是仅仅只是为了要两个下标都有标志,但是和数组的结构没有关系

我们从dp[i][i],也就是长度为1开始,保证j>i来确保最少子序列长度为1,然后往外部循环

如果新增加的i-1和j+1是相等的,这时的dp[i][j]就是他们里面的dp[i + 1][j - 1] 的加2

如果不是,则就需要选择到底是选择新的i - 1还是 j + 1了,我们取他们的最大值即可

正确代码

    public int longestPalindromeSubseq(String s) {
        int n = s.length();
        int[][] dp = new int[n][n];
        for (int i = n - 1; i >= 0; i--) {
            dp[i][i] = 1;
            char c1 = s.charAt(i);
            for (int j = i + 1; j < n; j++) {
                char c2 = s.charAt(j);
                if (c1 == c2) {
                    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][n - 1];
    }

总结

每次遇到各种的dp问题其实还是犯怵,找到状态方程不行,还得找到对应的结构来适配,还是做少了

如果文章存在问题或者更好的题解,欢迎在评论区斧正和评论,各自努力,你我最高处见

标签:Java,int,最长,序列,长度,回文,LeetCode,dp,516
来源: https://www.cnblogs.com/bc-song/p/15131078.html