力扣1143-最长公共子序列(Java详细题解)

题目链接:1143. 最长公共子序列 - 力扣(LeetCode)

前情提要:

如果你做过718. 最长重复子数组 - 力扣(LeetCode)并且看过我的这篇题解力扣718-最长重复子数组(Java详细题解)-CSDN博客,那么做这道题会简单很多。

因为本人最近都来刷dp类的题目所以该题就默认用dp方法来做。

dp五部曲。

1.确定dp数组和i下标的含义。

2.确定递推公式。

3.dp初始化。

4.确定dp的遍历顺序。

5.如果没有ac打印dp数组 利于debug。

每一个dp题目如果都用这五步分析清楚,那么这道题就能解出来了。

题目思路:

本题是要求俩个字符串的最长公共子序列的长度。注意这里的子序列和力扣718. 最长重复子数组的子序列不一样,本题的子序列是可以不连续的,而最长重复子数组是需要连续的。

话不多说,直接开始我们的dp五部曲。

1.确定dp数组和i下标的含义。

dp[i] [j]的含义是以i - 1结尾的字符串与j - 1结尾的字符串最长公共子序列的长度。

至于为什么是i- 1和j - 1大家可以看看这篇力扣718-最长重复子数组(Java详细题解)-CSDN博客

2.确定递推公式。

本题就难在递推公式。

因为我们要求最长公共子序列,可以是不连续的。

所以主要是俩大情况。一个是nums[i - 1] == nums[j - 1],

另一个就是不等于的情况。

当nums[i - 1] == nums[j - 1]时,说明此时结尾的元素相等,那么此时的最长公共子序列就等于他前一个状态加上相同元素的长度即可.

dp[i] [j] = dp[i - 1] [j - 1] + 1。

当nums[i - 1] != nums[j - 1]时,说明此时结尾的元素不等,那么此时我们就需要删除俩个数组中的最后一位元素。我们需要删除哪一个数组呢?

不知道,但是我们是要求最长的公共子序列的长度,所以我们取一个最大即可。

dp[i] [j] = Math.max(dp[i] [j - 1],dp[i - 1] [j]);

3.dp初始化。

由递推公式可以看出,最长公共子序列不仅由它左上的方向推出还可以由它左和上的方向推出。

所以第一排和第一列是递推的起点,我们就要初始化第一排和第一列。

因为dp[i] [0]和dp[0] [i]是将一个没有意义的字符串和另一个字符串求最长公共子序列,所以他们的长度就为0。

4.确定dp的遍历顺序。

由递推公式可以得出最长公共子序列不仅由它左上的方向推出还可以由它左和上的方向推出。

所以我们的遍历顺序是从左到右,从上到下。

5.如果没有ac打印dp数组 利于debug。

最终代码:

java 复制代码
class Solution {
    public int longestCommonSubsequence(String text1, String text2) {
        int [][] dp = new int [text1.length() + 1][text2.length() + 1];
        int result = 0;
        for(int i = 1;i <= text1.length();i ++){
            for(int j = 1;j <= text2.length();j ++){
                if(text1.charAt(i - 1) == text2.charAt(j - 1)){
                    //这里与最长重复子数组有一点区别 因为子数组是一种连续的结构 只要有一个不同 那么就不算重复的
                    //但是子序列不同 只要是在某一个界限前 一样的都算
                    //所以这里有俩种情况 当text1.charAt(i - 1) == text2.charAt(j - 1)时 那么就该把长度加一 俩个前一位的最长的公共子序列然后加1
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                }//如果不同 也有可能是有公共子序列的 比如 abc 与 ace 虽然最后一位不同 但他们是最长子序列为2
                //所以我们可以把拿abc以c结尾的字符串和ace以c为结尾字符串做对比
                //同理也可以拿abc以b为结尾的字符串与ace以e为结尾字符串做对比
                //抽象就是 最长公共子序列不仅由它左上的方向推出还可以由它左和上的方向推出
                else{
                    dp[i][j] = Math.max(dp[i - 1][j],dp[i][j - 1]);
                }text1.length()
                //这里顺便记录一下最长公共子序列的最大长度 其实也可以不用记录 返回dp[text1.length()][text2.length()]也可以
                    //因为本题所有的dp数组都会更新
                result = Math.max(result,dp[i][j]);
            }
        }
        return result;
    }
}

这一篇博客就到这了,如果你有什么疑问和想法可以打在评论区,或者私信我。

我很乐意为你解答。那么我们下篇再见!

相关推荐
你我约定有三13 分钟前
分布式微服务--Nacos作为配置中心(补)关于bosststrap.yml与@RefreshScope
java·分布式·spring cloud·微服务·架构
keepDXRcuriosity1 小时前
IDEA识别lombok注解问题
java·ide·intellij-idea
云边有个稻草人1 小时前
【C++】第二十一节—一文详解 | 红黑树实现(规则+效率+结构+插入+查找+验证)
算法·红黑树·红黑树的插入·红黑树的结构·红黑树完整代码·红黑树的效率·红黑树的查找
酷飞飞1 小时前
C语言的复合类型、内存管理、综合案例
java·c语言·前端
仟濹2 小时前
【C/C++】整数超过多少位时用「高精度」
c语言·c++·算法
宸津-代码粉碎机2 小时前
LLM 模型部署难题的技术突破:从轻量化到分布式推理的全栈解决方案
java·大数据·人工智能·分布式·python
都叫我大帅哥2 小时前
TOGAF实战解码:六大行业案例解析与成功启示
java
都叫我大帅哥2 小时前
RabbitMQ消息确认机制:从外卖小哥到数据安全的奇幻漂流
java·rabbitmq
周航宇JoeZhou5 小时前
JP3-3-MyClub后台后端(二)
java·mysql·vue·ssm·springboot·项目·myclub
DIY机器人工房5 小时前
一个可以检测本机的字节顺序,并对任意数据进行字节顺序的反转操作的代码。
嵌入式硬件·算法·嵌入式·diy机器人工房