LeetCode 516:最长回文子序列

LeetCode 516:最长回文子序列

🔗 题目链接

👉 https://leetcode.cn/problems/longest-palindromic-subsequence/

📖 题目概要

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

子序列 定义:不要求字符连续,在不改变原有字符顺序的前提下,可以删除某些字符(也可以不删除)得到新字符串。

回文定义:正读和反读完全一致的字符串。

示例

示例 1:

输入:s = "bbbab"

输出:4

解释:一个可能的最长回文子序列为 "bbbb"。

示例 2:

输入:s = "cbbd"

输出:2

解释:一个可能的最长回文子序列为 "bb"。

约束条件

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

📌 题目考点

  • 经典区间动态规划
  • 回文子序列 DP 模型(与最长回文子串区分)
  • 区间 DP 遍历顺序、状态转移逻辑考察
  • 字符串动态规划高频面试题

💡 解题思路

本题和「最长回文子串」不同:子序列不要求连续,因此解题思路采用标准区间 DP 求解。

1. 状态定义

定义二维 dp 数组:

dp[i][j] 表示字符串区间 s[i ... j] 中,最长回文子序列的长度。

2. 初始状态

单个字符一定是回文子序列,长度为 1。

因此初始化:dp[i][i] = 1(所有对角线位置赋值为 1)。

3. 状态转移方程

分两种情况讨论区间 [i, j]:

  1. 两端字符相等(s[i] == s[j])

    两端字符可以同时加入回文序列,结果为内部区间最长回文长度 + 2

    dpij=dpi+1j−1+2dpij = dpi+1j-1 + 2dpij=dpi+1j−1+2

  2. 两端字符不相等(s[i] != s[j])

    只能舍弃左端字符 或 舍弃右端字符,取两种情况的最大值:

    dpij=max⁡(dpi+1j,dpij−1)dpij = \max(dpi+1j, dpij-1)dpij=max(dpi+1j,dpij−1)

4. 遍历顺序(核心要点)

dp[i][j] 的结果依赖于:dp[i+1][j-1]、dp[i+1][j]、dp[i][j-1],也就是当前区间依赖更小的内层区间 / 下一行 / 前一列 。

因此遍历规则:

  • 左边界 i:从后往前遍历(从字符串末尾向开头)
  • 右边界 j:从 i+1 开始向后遍历(保证区间长度由小到大)

5. 最终答案

整个字符串对应区间 [0, len-1],最终返回 dp[0][len-1]。

✅ AC 代码

java 复制代码
class Solution {
    public int longestPalindromeSubseq(String s) {
        char[] ss = s.toCharArray();
        int len = s.length();
        int [][] dp = new int[len+1][len+1];
        
        // 初始化:单个字符最长回文子序列长度为 1
        for(int i = 0; i < len; i++) {
            dp[i][i] = 1;
        }

        // 左边界从后往前遍历
        for(int i = len - 1; i >= 0; i--) {
            // 右边界从 i+1 开始
            for(int j = i + 1; j < len; j++) {
                if(ss[i] == ss[j]) {
                    // 两端字符相等,内部结果 + 2
                    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][len-1];
    }
}

⏱️ 复杂度分析

指标 复杂度 说明
时间复杂度 O(n2)O(n^2)O(n2) 两层循环遍历所有区间,nnn 为字符串长度
空间复杂度 O(n2)O(n^2)O(n2) 开辟二维 dp 数组存储区间状态

💡 补充总结

  1. 区分易混点:最长回文子串(连续)、最长回文子序列(不连续),二者均常用区间 DP,但状态转移逻辑不同。
  2. 遍历顺序:区间 DP 通用规律,依赖内层子区间时,左边界逆序遍历。
  3. 基础边界:单个字符回文长度固定为 1,是 DP 初始化的关键。
相关推荐
招聘风控观察1 小时前
招聘质量管理是什么?招聘质量的定义与评价口径完整解释
职场和发展
徐小夕2 小时前
花了3个月,我们做了一款 AI 版的“飞书文档”
前端·算法·github
Robert--cao2 小时前
移动底盘与机械臂联合规划:开源算法与工程实现
算法
小豆庄3 小时前
Mac 上给视频人脸打码:本地工具的依赖、追踪与推理管线
算法·视觉检测·视频·敏捷流程·纹理贴图
星夜离尘563 小时前
MATLAB 工程实验:从相邻块均值手写重叠 Allan 偏差,数清有效项
算法·matlab·均值算法
y1su5 小时前
Leetcode 字符串模板
java·数据结构·算法·leetcode·职场和发展·动态规划
residual_fan6 小时前
船用柴油机动态机动工况故障诊断:控制感知仿射网络(CAAN)的技术实现
人工智能·算法·数据挖掘·数据分析
其实防守也摸鱼6 小时前
Cylab在线靶场——CTF中的通用技能
linux·数据库·学习·算法·靶场·ctf·学习网络安全
蓝悦无人机7 小时前
《Planning algorithms》读书笔记——第8章 反馈运动规划
算法·读书笔记·反馈运动规划
RaaS1007 小时前
Agent Skills 进了 Linux Foundation:2.8 亿次安装,但装 skill 还没有安全规范
人工智能·算法·架构