力扣HOT100之多维动态规划:1143. 最长公共子序列

这道题之前刷代码随想录的时候做过,但是现在又给忘干净了,这道题需要用二维dp数组来做,看了一下自己当时写的博客,一下子就看懂了。这道题的子序列可以不连续,所以dp数组的定义和最长重复子数组不一样,我总结出一个规律,**如果涉及到不连续的子序列,那么dp数组的定义就是第一个数组考虑0,i范围内元素,第二个数组考虑0,j范围内元素的情况下,两个数组之间的公共最长子序列的长度为dpij;如果涉及到连续的子序列,那么dp数组的定义就是,第一个数组以nums1i结尾,第二个数组以nums2j结尾的情况下,所能得到的最长公共子序列的长度。**这道题还是要反复刷呀。

下面给出动规五部曲:

1.确定dpij的含义:text1考虑下标0 ~ i - 1范围内的元素,text2考虑下标0 ~ j - 1范围内的元素所能取到的最长公共子序列长度为dp[i][j]

(1)当text1[i - 1] == text2[j - 1]dp[i][j] = dp[i - 1][j - 1] + 1;

(2)当text1[i - 1] != text2[j - 1]dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);

3.dp数组初始化 dp[0][0] = text1[0] == text2[0] ? 1 : 0;

4.确定遍历顺序:从左往右,从上往下遍历

5.打印数组(省略)

这里需要重点解释一下为什么dp数组要这样定义,因为假如我们这样定义:text1考虑下标0 ~ i范围内的元素,text2考虑下标0 ~ j范围内的元素所能取到的最长公共子序列长度为dp[i][j],那么我们在更新dp数组时,当text1[0] != text2[1]时,我们在执行dp[0][1] = max(dp[-1][1], dp[0][0]);时会发生越界访问,从而报错,我们很容易想到,我们无法将第0行和第0列通过简单的赋值进行初始化,这些元素的更新也需要借助复杂的递推公式,因此我们需要着重考虑如何在更新第0行和第0列时不发生越界访问,而将dp数组的下标与实际访问的字符串元素下标错开一位就能很好地解决这个问题。那么我们再回来看,当text1[0] != text2[1]时,我们会执行dp[1][2] = max(dp[0][2], dp[1][1]);那么dp[0][2]的初始值应该为多少?dp[0][2]的意义为:text1考虑下标0 ~ -1范围内的元素,text2考虑下标0 ~ 1范围内的元素所能取到的最长公共子序列长度为dp[0][2],很显然,text1没有合法元素可供比较,可以认为在这种情况下text1为空字符串,那么二者肯定不会存在公共子序列,因此dp[0][j]dp[i][0]都应全部初始化为0

至于递推公式,这个很容易想到,这里就不再赘述。

cpp 复制代码
class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {
        //1.确定dp[i][j]的含义:text1考虑下标0 ~ i - 1范围内的元素
        //text2考虑下标0 ~ j - 1范围内的元素所能取到的最长公共子序列长度为dp[i][j]
        //2.确定递推公式 
        //(1)当text1[i - 1] == text2[j - 1]时 dp[i][j] = dp[i - 1][j - 1] + 1;
        //(2)当text1[i - 1] != text2[j - 1]时 dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
        //3.dp数组初始化 dp[0][0] = text1[0] == text2[0] ? 1 : 0;
        //4.确定遍历顺序:从左往右,从上往下遍历
        //5.打印数组(省略)
        int m = text1.length();
        int n = text2.length();
        vector<vector<int>> dp(m + 1, vector<int> (n + 1, 0));  //初始化为全0数组
        for(int i = 1; i <= m; i++){
            for(int j = 1; j <= n; j++){
                if(text1[i - 1] == text2[j - 1])
                    dp[i][j] = dp[i][j] = dp[i - 1][j - 1] + 1;
                else
                    dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
            }
        }
        return dp[m][n];
    }
};
相关推荐
通信小呆呆3 小时前
当算法有了“五感”:多模态数据融合如何向人体感官协同学习?
人工智能·学习·算法·机器学习·机器人
benben0443 小时前
强化学习之DQN算法族(基于gymnasium开发)
算法
何以解忧,唯有..4 小时前
Go语言循环语句详解:for、range与循环控制
开发语言·算法·golang
想吃火锅10055 小时前
【leetcode】88.合并两个有序数组js
算法
生成论实验室6 小时前
机器人:一个自主运动的系统
人工智能·算法·语言模型·机器人·自动驾驶·agi·安全架构
Qres8216 小时前
算法复键——树状数组
数据结构·算法
H178535090966 小时前
SolidWorks第四部分_直接实体建模特征9_替换面原理
线性代数·算法·机器学习·3d建模·solidworks
不会就选b6 小时前
算法日常・每日刷题--<二分查找>3
算法
绿算技术7 小时前
Mooncake 与绿算ForinnBase GroundPool如何联手打破推理僵局?
科技·算法·架构