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

题目

516. 最长回文子序列

中等

相关标签

字符串 动态规划

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

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

示例 1:

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

示例 2:

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

提示:

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

思路和解题方法

  1. 首先,我们使用一个二维数组dp来存储子问题的解,其中dp[i][j]表示字符串s在位置i到位置j范围内的最长回文子序列的长度。
  2. 然后,我们初始化对角线上的值为1,表示单个字符本身就是一个回文子序列。
  3. 接下来,我们从字符串尾部开始向前遍历,在每个位置i和j之间进行计算。如果s[i]等于s[j],则s[i:j]范围内的最长回文子序列长度为s[i+1:j-1]范围内的最长回文子序列长度加2;如果s[i]不等于s[j],则s[i:j]范围内的最长回文子序列长度为s[i+1:j]和s[i:j-1]中的较大值。
  4. 最终,返回dp[0][s.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来存储子问题的解,其中dp[i][j]表示字符串s在位置i到位置j范围内的最长回文子序列的长度。
  • 然后,我们从字符串尾部开始向前遍历,确保不漏掉任何情况。在此过程中,我们对dp数组进行初始化,并且通过动态规划的方法逐步填充dp数组。
  • 最后,返回dp[0][len - 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];  // 返回整个字符串的最长回文子序列长度
    }
}

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

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

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

相关推荐
UestcXiye1 小时前
《TCP/IP网络编程》学习笔记 | Chapter 3:地址族与数据序列
c++·计算机网络·ip·tcp
测开小菜鸟1 小时前
使用python向钉钉群聊发送消息
java·python·钉钉
好奇龙猫2 小时前
【学习AI-相关路程-mnist手写数字分类-win-硬件:windows-自我学习AI-实验步骤-全连接神经网络(BPnetwork)-操作流程(3) 】
人工智能·算法
P.H. Infinity2 小时前
【RabbitMQ】04-发送者可靠性
java·rabbitmq·java-rabbitmq
生命几十年3万天3 小时前
java的threadlocal为何内存泄漏
java
霁月风3 小时前
设计模式——适配器模式
c++·适配器模式
sp_fyf_20243 小时前
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-11-01
人工智能·深度学习·神经网络·算法·机器学习·语言模型·数据挖掘
caridle3 小时前
教程:使用 InterBase Express 访问数据库(五):TIBTransaction
java·数据库·express
^velpro^3 小时前
数据库连接池的创建
java·开发语言·数据库
苹果醋33 小时前
Java8->Java19的初步探索
java·运维·spring boot·mysql·nginx