【刷题篇】最长公共子序列

一、题目

OJ链接
给定两个字符串,返回两个字符串的最长公共子序列的长度。
【注意】:
子序列可以不连续,子字符串一定是要连续的

二、题解

2.1 方法一:递归

思路:
对于给定的两个字符串str1,str2
只关心str1[0,i] 和 str2[0,j] 这两个范围内的字符串的最长公共子序列。
递归函数:
对于递归函数只求str1[0…i]和str[0…j]的最长公共子序列
终止条件:
当i和j都为0的时候,说明两个字符串都只有一个字符,如果这两个字符相等就返回1,否则返回0

当i==0但j!=0时,说明str1中只剩一个字符,和str2[0…j]最多只有一个公共子序列,先判断str1中这个字符是否和str1[j]位置字符相等,如果相等直接返回1,不相等的话就不需要考虑j位置对应的字符了,只需找出str2[0…j-1]与str1中这一个字符的最长公共子序列。

当i!=0 但j==0,和上一种情况类似
在这里插入图片描述
当i和j都不等于0的时候
在这里插入图片描述
源码:
👽


    public  static int longestCommonSubsequence(String s1, String s2) {
          if(s1==null||s1.length()==0||s2==null||s2.length()==0){
              return 0;
          }
            char[] str1=s1.toCharArray();
             char[] str2=s2.toCharArray();

             return process1(str1,str2,str1.length-1,str2.length-1);
    }


    //str1[0...i]和str2[0....j]的最长公共子序列
    public static int  process1(char[] str1,char[] str2,int i,int j){
           if(i==0&&j==0){
               return str1[i]==str2[j]?1:0;
           } else if(i==0){
               if(str1[i]==str2[j]){
                   return 1;
               }else{
                   return process1(str1,str2,i,j-1);
               }
           }  else if(j==0){
               if(str1[i]==str2[j]){
                   return 1;
               }else{
                   return process1(str1,str2,i-1,j);
               }
           } else { //i!=0 && j!=0

                    int p1=process1(str1,str2,i-1,j);
                    int p2=process1(str1,str2,i,j-1);
                    int p3=str1[i]==str2[j]?(1+process1(str1,str2,i-1,j-1)):0;

                    return Math.max(p3,Math.max(p1,p2));
           }

    }

2.2 方法二:动态规划

在这里插入图片描述
源码:
😇

 public  static int longestCommonSubsequence2(String s1, String s2) {
        if(s1==null||s1.length()==0||s2==null||s2.length()==0){
            return 0;
        }
        char[] str1=s1.toCharArray();
        char[] str2=s2.toCharArray();
        int N=str1.length;
        int M=str2.length;
        int[][] dp=new int[N][M];
         dp[0][0]=str1[0]==str2[0]?1:0;
        for (int j = 1; j< M; j++) {
           dp[0][j]=str1[0]==str2[j]?1:dp[0][j-1];
        }
        for (int i = 1; i <N ; i++) {
            dp[i][0]=str1[i]==str2[0]?1:dp[i-1][0];
        }

        for (int i = 1; i <N ; i++) {
            for (int j = 1; j <M ; j++) {
                int p1=dp[i-1][j];
                int p2=dp[i][j-1];
                int p3=str1[i]==str2[j]?(1+dp[i-1][j-1]):0;
               dp[i][j]= Math.max(p3,Math.max(p1,p2));
            }
        }

        return dp[N-1][M-1];
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值