leetcode每日一题 2021/4/3 1143. 最长公共子序列

题目:

给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 0 。

一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。

例如,"ace" 是 "abcde" 的子序列,但 "aec" 不是 "abcde" 的子序列。
两个字符串的 公共子序列 是这两个字符串所共同拥有的子序列。

示例 1:

输入:text1 = "abcde", text2 = "ace"
输出:3
解释:最长公共子序列是 "ace" ,它的长度为 3 。

示例 2:

输入:text1 = "abc", text2 = "abc"
输出:3
解释:最长公共子序列是 "abc" ,它的长度为 3 。

示例 3:

输入:text1 = "abc", text2 = "def"
输出:0
解释:两个字符串没有公共子序列,返回 0 。

提示:

1 <= text1.length, text2.length <= 1000
text1 和 text2 仅由小写英文字符组成。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-common-subsequence
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

这是一道简单的动态规划入门题;
以 text1 = "abcde", text2 = "ace" 为例
我们可以构建一个这样的二维数组


在这里插入图片描述

其中第i行和第j位的数字代表text1前i位和text2前j位的最大公共子序列,好了,我们知道了要构建这么一个二维数组,后面说到的res代表的就是该数组。但是这个数组要怎么构建起来呢?首先我们就应该要找出规律,写出它的动态转移方程。
需要分两种情况:
(1)text1[i] == text2[j]
这种情况下说明当前的元素可以是公共的元素,我们可以在text1[1 ~ (i-1)] (注:取第一位到第第i-1位)和text2[1 ~ (j-1)]的最长公共子序列的基础上加1,也就是res[i][j] = res[i-1][j-1] + 1;
(2)tex1[i] != text2[j]
这种情况下我们有两个选择
① 选择text1[1 ~ (i-1)] 和 text2[1 ~ j]的最长公共子序列
② 选择text1[1 ~ i] 和 text2[1 ~ (j-1)]的最长公共子序列
而我们要的是最优解,所以肯定要选择这两者中的最大者,也就是:
res[i][j] = max(res[i-1][j],res[i][j-1])
至此,我们已经得出了它的动态转移方程,接下来只要用代码来实现就可以了。

代码

javascript

var longestCommonSubsequence = function(text1, text2) {
    let res = new Array(text1.length + 1);
    for(let i = 0; i <= text1.length; i++){
        res[i] = new Array(text2.length + 1).fill(0);
    }
    for(let i = 1; i <= text1.length; i++){
        for(let j = 1; j <= text2.length; j++){
            if(text1[i-1] == text2[j - 1]){
                res[i][j] = res[i - 1][j - 1] + 1;
            }else{
                res[i][j] = Math.max(res[i - 1][j],res[i][j - 1]);
            }
        }
    }
    return res[text1.length][text2.length];
};

C语言

#include
int longestCommonSubsequence(char * text1, char * text2){
    int res[1005][1005],
        n = strlen(text1),
        m = strlen(text2);
    for(int i = 0; i <= n; i++){
        res[i][0] = 0;
    }
    for(int i = 0; i <= m; i++){
        res[0][i] = 0;
    }
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){
            if(text1[i - 1] == text2[j - 1]){
                res[i][j] = res[i - 1][j - 1] + 1;
            }else{
                res[i][j] = res[i - 1][j] > res[i][j - 1] ? res[i - 1][j] : res[i][j - 1];
            }
        }
    }
    return res[n][m];
}

python

class Solution:
    def longestCommonSubsequence(self, text1: str, text2: str) -> int:
        m = len(text1)
        n = len(text2)
        res = [[0] * (n + 1) for i in range(m + 1)]
        for i in range(1,m+1):
            for j in range(1,n+1):
                if(text1[i - 1] == text2[j - 1]):
                    res[i][j] = res[i - 1][j - 1] + 1
                else:
                    res[i][j] = res[i - 1][j] if res[i - 1][j] > res[i][j - 1] else res[i][j - 1]
        return res[m][n]

你可能感兴趣的:(leetcode每日一题 2021/4/3 1143. 最长公共子序列)