『LeetCode|每日一题』---->最长公共子序列

目录

每日一句

作者简介 

 『LeetCode|每日一题』 最长公共子序列

1.每日一题

2.解题思路 

        2.1 思路分析

        2.2 核心代码(dp)

        2.3 全部代码 

        2.4 运行结果 

3.第二种解法(递归)----此题中会超时 

        3.1 全部代码

        3.2 解析

        3.3 运行结果 


每日一句

给予和就受都是一份馈赠,既需要谦逊,也需要勇气

作者简介 

🏡个人主页:XiaoChen_Android

📚学习专栏:力扣专栏

🕒发布日期:2022/8/18

在这里插入图片描述

 『LeetCode|每日一题』 最长公共子序列

1.每日一题

原文链接---快看看

2.解题思路 

        2.1 思路分析

此题是二维动态规划中的一道经典例题,定义一个二维数组dp[i][j],用来存两个字符串text1(0,i)和text2(0,j)中的最长公共子序列

        S1:dp数组的长度可以扩大一位,左边界和上边界的值都为0;(当i = 0时,该字符串为空,所以值为0,这一步就是处理了动态规划的边界情况,读者可以仔细想想为何这么处理)

        S2:当i > 0 ,j > 0时,开始填充dp数组,分为两种情况:(由于考虑的dp[i][j]的值,它减少一位字符则由字符串的前一位决定)

  • 当text1.charAt(i - 1) == text2.charAt(j - 1)时,再增加一位字符就得到了dp[i][j],dp[i][j] = dp[i - 1][j - 1] + 1;
  • 当text1.charAt(i - 1) != text2.charAt(j - 1)时,考虑两种情况:
    • text1范围在(0,i)和text2范围在(0.j -1)的最长公共子序列 
    • text1范围在(0,i - 1)和text2范围在(0.j)的最长公共子序列       
  • 要使得dp[i][j]最大,则应该取dp[i][j - 1]和dp[i - 1][j]中的最大值

        S3:最终计算得到的dp[text1.length()][text2.length()]就是最长公共子序列的长度

        2.2 核心代码(dp)

        for(int i = 1 ; i <= l1 ; i ++){
            for(int j = 1 ; j <= l2 ; j ++){
                if(t1[i - 1] == t2[j - 1]){
                    dp[i][j] = dp[i - 1][j - 1] + 1; 
                }else {
                    dp[i][j] = Math.max(dp[i - 1][j] , dp[i][j - 1]);
                }
            }
        }

        2.3 全部代码 

class Solution {
    public int longestCommonSubsequence(String text1, String text2) {
        int l1 = text1.length();
        int l2 = text2.length();
        char[] t1 = new char[l1];
        char[] t2 = new char[l2];
        int[][] dp = new int[l1 + 1][l2 + 1];
        for(int i = 0 ; i < l1 ; i ++){
            t1[i] = text1.charAt(i);
        }
        for(int i = 0 ; i < l2 ; i ++){
            t2[i] = text2.charAt(i);
        }
        
        for(int i = 1 ; i <= l1 ; i ++){
            for(int j = 1 ; j <= l2 ; j ++){
                if(t1[i - 1] == t2[j - 1]){
                    dp[i][j] = dp[i - 1][j - 1] + 1; 
                }else {
                    dp[i][j] = Math.max(dp[i - 1][j] , dp[i][j - 1]);
                }
            }
        }

        return dp[l1][l2];
    }
    
}

        2.4 运行结果 

3.第二种解法(递归)----此题中会超时 

        3.1 全部代码

class Solution {
    public int longestCommonSubsequence(String text1, String text2) {
        int l1 = text1.length();
        int l2 = text2.length();
        char[] t1 = new char[l1];
        char[] t2 = new char[l2];
        
        for(int i = 0 ; i < l1 ; i ++){
            t1[i] = text1.charAt(i);
        }
        for(int i = 0 ; i < l2 ; i ++){
            t2[i] = text2.charAt(i);
        }
        int ans = dp(t1 , t2 , l1 , l2);
        return ans;
    }
    private static int dp(char[] t1 , char[] t2 , int l1 , int l2){
        int[][] cc = new int[l1 + 1][l2 + 1];
        if(l1 == 0 || l2 == 0){
            return 0;
        }else if(t1[l1 - 1] == t2[l2 - 1]){
            cc[l1][l2] = dp(t1 , t2 , l1 - 1 , l2 - 1) + 1;
        }else {
            cc[l1][l2] = Math.max(dp(t1 , t2 , l1 - 1 , l2) , dp(t1 , t2 , l1 , l2 - 1));
        }
        return cc[l1][l2];

    }
}

         3.2 解析

思路同dp解法类似,不过这个方法的边界处理是用长度来取代的,即l1 == 0 || l2 == 0

众所周知,递归虽然容易理解,但是递归的过程是非常耗时的,在对时间复杂度没有要求的情况下可以用递归求解,否则用动态规划是最为合理的

        3.3 运行结果 


🍁 类似题目推荐:

1.剑指offer专项练习 

2.算法专项练习 

3.推荐一个学习网站:LeetCode,算法的提升在于日积月累,只有每天练习才能保持良好的状态

如果文章对你有帮助就支持一下噢,新手尝试,不好的地方请各位大佬多多指教! 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值