leetcode 516. 最长回文子序列(JAVA)题解

题目链接https://leetcode.cn/problems/longest-palindromic-subsequence/description/?utm_source=LCUS&utm_medium=ip_redirect&utm_campaign=transfer2china

目录

题目描述:

暴力递归:

动态规划:


题目描述:

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

示例 1:

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

示例 2:

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

提示:

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

这道题的知识点是动态规划,可是如果直接从动态规划讲可能有点不容易理解。

所以本篇文章就是从暴力递归到动态规划。

从题目中我们可以得出:本题找的是可以不连续的回文子串然后返回其最大序列的长度。

也就是说:

a2b42a

的最长回文子序列为:a2b2a或a242a 这两个都可以 因为它们返回的都是5

暴力递归:

我们先写一个可以返回最长的回文子序列长度的函数:

java 复制代码
//主函数
public int longestPalindromeSubseq(String s) {
        char[] str = s.toCharArray();
        return maxString(str, 0, str.length-1);
}

//假设该函数可以返回最长回文子序列的长度
public static int maxString(char[] str, int l, int r) {}

我们写的 maxString() 方法可以返回 str 字符串l, r区间的最长回文子序列的长度 。

通过分析可以得出以下结论:

两种特殊情况:

  • 首先我们可以得到当 l 和 r 相等就证明此时只有一个字符那么它的返回值就是 1 。
  • 如果传入的数组只有两个字符即 l + 1 == r 那么此时如果这两个字符相等就返回 2,如果不相等就返回 1。

普遍情况:

  • 两边的字符都不存在于最长的回文子序列中。例:a1221b -> 1221;
  • 右边的字符****不存在在于最长的回文子序列中。例:1221b -> 1221;
  • 左边的字符****不存在在于最长的回文子序列中。例:a1221 -> 1221;
  • 两边的字符 都存在于最长的回文子序列中。例:1w221 -> 1221。

此时代码就可以这样写:

java 复制代码
//主函数
public int longestPalindromeSubseq(String s) {
        char[] str = s.toCharArray();
        return maxString(str, 0, str.length-1);
}

//假设该函数可以返回最长回文子序列的长度
public static int maxString(char[] str, int l, int r) {
        //先判断两种特殊情况
        if (l == r){
            return 1;
        }
        if (l + 1 == r){
            return str[l] == str[r] ? 2 : 1;
        }
        //余下的四种情况
        int a1 = maxString(str, l + 1, r - 1);
        int a2 = maxString(str, l, r - 1);
        int a3 = maxString(str, l + 1, r);
        int a4 = str[l] == str[r] ? 2 + maxString(str, l + 1, r - 1) : 0;
        
        //因为题目要求返回最长序列长度  所以需要返回这四个的最大值
        return Math.max(Math.max(a1, a2), Math.max(a3, a4));
}

此时我们可以提交以下:

虽然没通过但是从它的报错信息可以看出,我们的思路是没问题的。

动态规划:

我们有了递归版本后就可以根据它来写出动态规划版本了。

因为在maxString() 方法中只有 l 和 r 是变量,而它们两个的取值范围都是 0,str.length - 1

此时我们就可以通过创建一个二维数组将 l 和 r所有情况都列举出来然后返回数组0,str.length - 1 下标的值就可以得出答案了。

我们先假设长度只有 5 ,那么我们就可以创建如下的二维数组l 行,r 列

java 复制代码
public static int maxString(char[] str, int l, int r) {

        int[][] arr = new int[str.length][str.length];
        
}

接下来的填表阶段就可以根据递归函数直接填(以"a1221"为例子):

此时 0, 4 位置的值就是最终答案。

根据每个位置的关系就将递归优化成:

java 复制代码
public static int maxString(char[] str, int l, int r) {

        int[][] arr = new int[str.length][str.length];
        //因为不存在l < r的情况所以下三角的空间不用
        for (int i = 0; i < str.length; i++) {
            if (i == 0){//填第一条对角线
                int j = 0;
                while(j < str.length) {
                    arr[j][j] = 1;
                    j++;
                }
            }else if (i == 1) {//填第二条斜线
                int j = 1;
                while(j < str.length) {
                    arr[j - 1][j] = (str[j - 1] == str[j]) ? 2 : 1;
                    j++;
                }
            }else {//其他
                int j = i;
                int k = 0;
                while(j < str.length){
                    int a1 = arr[k + 1][j - 1];
                    int a2 = arr[k][j - 1];
                    int a3 = arr[k + 1][j];
                    int a4 = str[k] == str[j] ? 2 + arr[k + 1][j - 1] : 0;
                    arr[k][j] = Math.max(Math.max(a1, a2), Math.max(a3, a4));
                    j++;
                    k++;
                }
            }

        }
        return arr[0][str.length-1];
}

此时再提交就过了。

相关推荐
非优秀程序员7 小时前
第05章 播放器大战,暴风、快播与那一夜|《互联网产品恩仇录》
算法
非优秀程序员7 小时前
第04章 邮箱大战,163 与 QQ 的暗战|《互联网产品恩仇录》
java·vue.js·架构
知已难寻8 小时前
Docker 入门:容器技术与 Docker 基础
java·运维·服务器·docker·云原生·容器
沐晓时光8 小时前
C语言入门,内存函数知识讲解
c语言·开发语言
文丑颜不良啊10 小时前
LeetCode2481~2500题目解析
java·leetcode
Flynn Liang11 小时前
同一需求三套写法:用 Spring AI、LangChain4j、AgentScope Java 各实现一个带工具调用的 RAG 助手(实战对比)
java·人工智能·大模型·架构设计·spring ai·langchain4j·agentscope
聪明的笨猪猪12 小时前
实际工程问题:AI 生成 Spring Cache(@Cacheable / @CachePut / @CacheEvict)缓存注解踩坑
java·经验分享·面试·ai编程
愿有所息12 小时前
记一次 ARM64 + JDK8 上 fastjson2 的诡异数据错乱
java
秋饼12 小时前
MCP 2026-07-28 无状态协议大改版:Spring AI 2.1 多轮往返请求与网关路由落地
java·ai·技术分享·后端开发