【左程云|程序员代码面试指南】 最长公共子序列(动态规划Java版)

【题目详情】

给定两个字符串str1和str2,输出连个字符串的最长公共子序列。如过最长公共子序列为空,则输出-1。具体见牛客官网,首页 > 在线编程 > 程序员代码面试指南查看提交。链接直达

【输入描述】

输出包括两行,第一行代表字符串str1,第二行代表str2。
(1≤length(str1),length(str2)≤5000)

【输出描述】

输出一行,代表他们最长公共子序列。如果公共子序列的长度为空,则输出-1。

【复杂度】
  • 时间复杂度O(n*m)O(n∗m)
  • 空间复杂度O(n*m)O(n∗m)。(n,m分别表示两个字符串长度)
【完整代码】
import java.util.Scanner;

public class Main{
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String str1 = sc.next();
        String str2 = sc.next();
        System.out.println(lcse(str1, str2));
    }
    public static int[][] getdp(String str1, String str2)
    {
        int[][] dp = new int[str1.length()][str2.length()];
        char[] str1Arr = str1.toCharArray();
        char[] str2Arr = str2.toCharArray();
        dp[0][0] = str1Arr[0] == str2Arr[0] ? 1 : 0 ;
        for(int i = 1; i < str1.length(); i++)
        {
            //第零列
            dp[i][0] = Math.max(dp[i-1][0], (str1Arr[i] == str2Arr[0] ? 1 : 0));
        }
        for(int j = 1; j < str2.length(); j++)
        {
            //第零行
            dp[0][j] = Math.max(dp[0][j-1], (str1Arr[0] == str2Arr[j] ? 1 : 0));
        }
        for(int i = 1; i < str1.length(); i++)
        {
            for(int j = 1; j < str2.length(); j++)
            {
                //先比较左和上,取大者
                dp[i][j] = Math.max(dp[i][j-1], dp[i-1][j]);
                if(str1Arr[i] == str2Arr[j])
                {
                    dp[i][j] = Math.max(dp[i-1][j-1]+1, dp[i][j]);
                }
            }
        }
        return dp;
    }
    public static String lcse(String str1, String str2)
    {
        int m = str1.length()-1;
        int n = str2.length()-1;
        int[][] dp = new int[m+1][n+1];
        dp = getdp(str1, str2);
        char[] res = new char[dp[m][n]];
        char[] str1Arr = str1.toCharArray();
        char[] str2Arr = str2.toCharArray();
        if(str1 == null || str2 == null || str1.equals("") || str2.equals("") || dp[m][n] == 0)
        {
            return "-1";
        }
        int index = res.length - 1;
        //比如res数组长度为7,实际计算过程并不是7次,而是大于等于7次
        while(index >= 0)
        {
            if(n > 0 && dp[m][n] == dp[m][n-1])//来自左
            {
                n--;
            }
            else if(m > 0 && dp[m][n] == dp[m-1][n])//来自上
            {
                m--;
            }
            else
            {
                //dp[m][n] == dp[m-1][n-1] + 1 || dp[0][n] == dp[0][n-1] + 1 || dp[m][0] == dp[m-1][0] + 1
                res[index--] = str1Arr[m];
                m--;
                n--;
            }
        }
        return String.valueOf(res);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
左程动态规划题型方面有一些相关的讲解和课程。动态规划是一种常见的算法设计技巧,可以解决一些具有重叠子问题性质的问题。通过分解问题为子问题,然后根据子问题的解推导出原问题的解。引用中提到了左程算法课堂上有动态规划相关的题目。还有一些其他的题目也可以在LeetCode上找到,比如[1108. IP 地址无效化(简单)]、[344. 反转字符串(简单)]以及[剑指 Offer 58 - I. 翻转单词顺序(简单)]等。所以,如果对动态规划感兴趣,可以参考左程的课堂和LeetCode上的相关题目进行练习。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [出自算法之神“左程”的这本《算法面试指南》被LeetCode官推,秀我一脸~](https://blog.csdn.net/SharingOfficer/article/details/121523204)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [左程leetcode-LeetCode:力扣解决方案](https://download.csdn.net/download/weixin_38556416/19925757)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值