当前位置: 首页 > article >正文

力扣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。

在这里插入图片描述

最终代码:

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;
    }
}

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

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


http://www.kler.cn/a/314118.html

相关文章:

  • Pytorch如何将嵌套的dict类型数据加载到GPU
  • Android音视频直播低延迟探究之:WLAN低延迟模式
  • 【论文阅读】Virtual Compiler Is All You Need For Assembly Code Search
  • kubernetes简单入门实战
  • python怎么设置环境变量
  • python——面向对象
  • 分布式光伏发电系统如何确保电能质量达到并网要求?
  • Tiny-universe学习笔记1:Qwen-blog
  • 数据飞轮:打造业务增长的持续循环
  • C++——string的了解和使用
  • 相见恨晚的一本书《纳瓦尔宝典:财富与幸福指南》
  • 内网渗透- 内网渗透的基本知识
  • 【物联网】时序数据库InfluxDB解析及1.x版本与2.x版本区别详解
  • Docker 笔记
  • java计算字符串中大写字母的个数
  • 30道常见的软件测试面试题(含答案+文档)
  • 【若依框架】按时间查询数据的操作
  • VScode 使用Code Runner 运行输出控制台中文乱码解决
  • Qt中的延时
  • 基于TCP实现聊天
  • Spring中的Web Service消费者集成(应该被淘汰的技术)
  • c++实现类
  • React基础教程(10):React Hooks
  • 1.4 MySql配置文件
  • C++学习笔记(24)
  • Spring Boot-应用启动问题