LeetCode--1143:最长公共子序列(java)

原题链接
1.暴力解法
枚举 text1 的所有子序列,看该子序列是否在 text2 中,时间复杂度O(2n)。
2.动态规划
本文根据覃超老师讲解所写
用二维数组 dp 来存储最长公共子序列的长度,行和列分别代表不同的字符串。
例如:
LeetCode--1143:最长公共子序列(java)_第1张图片
二维数组中的值表示的是蓝色字符串当前子序列红色字符串当前子序列的公共子序列长度。
(0, 0) :蓝色字符串当前子序列为 蓝B,红色字符串当前子序列为 红A,很明显公共子序列长度为 0。
(0, 1) :蓝色字符串当前子序列为 蓝B,红色字符串当前子序列为 红AB,因为都有B,所以公共子序列长度为 1。

(0, 4) :蓝色字符串当前子序列为 蓝B,红色字符串当前子序列为 红ABAZD,只有一个公共B,所以公共子序列长度为 1。

(2, 2):蓝色字符串当前子序列为 蓝BAC,红色字符串当前子序列为 红ABA,公共子序列为BA,所以公共子序列长度为 2。

(5, 5):蓝色字符串当前子序列为 蓝BACBAD,红色字符串当前子序列为 红ABAZDC,公共子序列为ABAD,所以公共子序列长度为 4。

算法结束时返回数组最后一个元素即可。

动态转移方程:

考虑 S1i 与 S2j 值是否相等,分为两种情况:
在这里插入图片描述
蓝色字符串为S1,红色字符串为S2。
       先说S1i = S2j,例如(2, 5)= 3 这个值,3 怎么来的?此时的蓝色字符串当前子序列为蓝BAC,红色字符串当前子序列为 红ABAZDC。因为 S12 = C,S25 = C,所以(2,5)的值就是蓝BA和红ABAZD的公共子序列长度+1,也就是(1, 4)+ 1 = 3。即dp[i][j] = 左上角的值+1
       再说S1i != S2j,例如(4, 1)= 2 这个值,2 怎么来的?此时的蓝色字符串当前子序列为蓝BACBA,红色字符串当前子序列为 红AB。因为 S14 = A,S21 = B,这俩不相等,所以(4,1)的值就是蓝BACB和红AB的公共子序列长度蓝BACBA 和红A的公共子序列长度 中的较大值,也就是max((3,1),(4,0))。即dp[i][j] = max(左边的值,上边的值)

class Solution {
    public int longestCommonSubsequence(String text1, String text2) {
        if(text1 == null || text2 == null) return 0;
        int m = text1.length();
        int n = text2.length();
      //多申请一行一列,是因为dp[0][0]需要处理越界,所以改成dp[1][1]
        int[][] dp = new int[m + 1][n + 1];
        for(int i = 1;i <= m;i++) {
        	for(int j = 1;j <= n;j++) {
        		if(text1.charAt(i - 1) == text2.charAt(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[m][n];
    }
}

在这里插入图片描述

你可能感兴趣的:(LeetCode)