力扣第516题 最长回文子序列 c++ 动态规划 附Java代码 注释版

题目

516. 最长回文子序列

中等

相关标签

字符串 动态规划

给你一个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度。

子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。

示例 1:

复制代码
输入:s = "bbbab"
输出:4
解释:一个可能的最长回文子序列为 "bbbb" 。

示例 2:

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

提示:

  • 1 <= s.length <= 1000
  • s 仅由小写英文字母组成

思路和解题方法

  1. 首先,我们使用一个二维数组dp来存储子问题的解,其中dpij表示字符串s在位置i到位置j范围内的最长回文子序列的长度。
  2. 然后,我们初始化对角线上的值为1,表示单个字符本身就是一个回文子序列。
  3. 接下来,我们从字符串尾部开始向前遍历,在每个位置i和j之间进行计算。如果si等于sj,则si:j范围内的最长回文子序列长度为si+1:j-1范围内的最长回文子序列长度加2;如果si不等于sj,则si:j范围内的最长回文子序列长度为si+1:j和si:j-1中的较大值。
  4. 最终,返回dp0s.size() - 1,即整个字符串的最长回文子序列长度。

打印的dp数组

a b c b a

复杂度

时间复杂度:

O(n*n)

时间复杂度是O(n^2),其中n为输入字符串s的长度。这是因为我们使用了一个二维数组dp来存储子问题的解,然后使用两层嵌套的循环来填充这个数组,每次循环都需要考虑当前字符以及其之前的所有字符,因此时间复杂度为O(n^2)。

空间复杂度

O(n*n)

空间复杂度也是O(n^2),因为我们使用了一个二维数组dp来存储子问题的解,其大小为n*n。

c++ 代码

cpp 复制代码
class Solution {
public:
    int longestPalindromeSubseq(string s) {
        // 创建二维数组dp来存储子问题的解,dp[i][j]表示s[i:j]范围内的最长回文子序列长度
        vector<vector<int>> dp(s.size(), vector<int>(s.size(), 0));
        
        // 初始化对角线上的值为1,即单个字符本身就是一个回文子序列
        for (int i = 0; i < s.size(); i++) {
            dp[i][i] = 1;
        }
        
        // 从字符串尾部开始遍历
        for (int i = s.size() - 1; i >= 0; i--) {
            // 从当前字符向后遍历
            for (int j = i + 1; j < s.size(); j++) {
                if (s[i] == s[j]) {
                    // 如果s[i]等于s[j],则s[i:j]范围内的最长回文子序列长度为s[i+1:j-1]范围内的最长回文子序列长度加2
                    dp[i][j] = dp[i + 1][j - 1] + 2;
                } else {
                    // 如果s[i]不等于s[j],则s[i:j]范围内的最长回文子序列长度为s[i+1:j]和s[i:j-1]中的较大值
                    dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);
                }
            }
        }
        
        // 返回整个字符串的最长回文子序列长度
        return dp[0][s.size() - 1];
    }
};

Java代码

  • 首先,我们定义了一个二维数组dp来存储子问题的解,其中dpij表示字符串s在位置i到位置j范围内的最长回文子序列的长度。
  • 然后,我们从字符串尾部开始向前遍历,确保不漏掉任何情况。在此过程中,我们对dp数组进行初始化,并且通过动态规划的方法逐步填充dp数组。
  • 最后,返回dp0len - 1,即整个字符串的最长回文子序列长度。
java 复制代码
public class Solution {
    public int longestPalindromeSubseq(String s) {
        int len = s.length();
        int[][] dp = new int[len + 1][len + 1];  // 创建二维数组dp来存储子问题的解,dp[i][j]表示s[i:j]范围内的最长回文子序列长度
        for (int i = len - 1; i >= 0; i--) {  // 从后往前遍历,保证情况不漏
            dp[i][i] = 1;  // 初始化对角线上的值为1,即单个字符本身就是一个回文子序列
            for (int j = i + 1; j < len; j++) {
                if (s.charAt(i) == s.charAt(j)) {
                    dp[i][j] = dp[i + 1][j - 1] + 2;  // 如果s[i]等于s[j],则s[i:j]范围内的最长回文子序列长度为s[i+1:j-1]范围内的最长回文子序列长度加2
                } else {
                    dp[i][j] = Math.max(dp[i + 1][j], Math.max(dp[i][j], dp[i][j - 1]));  // 如果s[i]不等于s[j],则s[i:j]范围内的最长回文子序列长度为s[i+1:j]和s[i:j-1]中的较大值
                }
            }
        }
        return dp[0][len - 1];  // 返回整个字符串的最长回文子序列长度
    }
}

觉得有用的话可以点点赞,支持一下。

如果愿意的话关注一下。会对你有更多的帮助。

每天都会不定时更新哦 >人< 。

相关推荐
ym hyd 1113 小时前
试题库管理系统源码 Java+SpringBoot+Vue3 前后分离
java·vue.js·spring boot·毕设
AC赳赳老秦3 小时前
采集行为合规自检:OpenClaw 自动校验 robots 协议与采集频率,规避违规采集风险
java·开发语言·c++·python·php·deepseek·openclaw
钱栈up3 小时前
mvn compile 卡死在 javac 阶段:一次类型不匹配的排查与修复
java·开发语言
无名猿4 小时前
C++ 查找算法:std::find 与容器成员 find 的性能差距
c++·性能优化·stl·标准库
程序猿编码4 小时前
工业视觉多任务方案:可编程梯度信息视觉框架,训练评估 + C++ 部署完整实战
开发语言·c++·视觉·推理引擎
吠品5 小时前
CSS图片模糊过渡:一个transition加filter就够
java·数据库·notepad++
朝朝辞暮i5 小时前
C++ 第 21 课:struct —— 把一组相关数据打包在一起
开发语言·c++·算法
步行cgn5 小时前
Spring 全注解开发详解
java·后端·spring
青梅橘子皮5 小时前
Blue---二分算法(二分查找与二分答案)
算法
长河6 小时前
Java的GC(垃圾回收)中,标记无用对象的核心方法是可达性分析算法
java·jvm·算法