DAY53:动态规划(十八)最长公共子序列+不相交的线+最大子序列和

文章介绍了如何使用动态规划解决最长公共子序列和不相交的线问题,强调了保持元素顺序的重要性。对于最长公共子序列,解释了如何处理不连续的情况,并给出了递推公式和初始化步骤。对于不相交的线,同样利用动态规划,关键在于保持数字顺序以避免线条相交。此外,还讨论了最大子序列和问题,提供了贪心和动态规划两种解法,并分析了不同思路的适用性。
摘要由CSDN通过智能技术生成

1143.最长公共子序列(注意递推的逻辑)

  • 体会一下本题和 718. 最长重复子数组 的区别,主要是本题不连续,不连续的递推逻辑一定要注意

给定两个字符串 text1text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 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
  • text1text2 仅由小写英文字符组成。

思路

本题与 718.最长重复子数组 的区别就在于,本题不要求两个数组的重复元素连续了,但是需要保持元素的相对顺序

如果不需要保持元素连续,那么一个重要区别就是,字符串包含的数字越多,两个数组的重复元素存在的可能性越高,包含数字多的字符串重复元素数量一定>=包含数字少的

DP数组含义

这类需要两个序列挨个对比的题目,DP数组含义最好都设置为:长度为[0,i-1]的字符串1和长度为[0,j-1]的字符串2,两个字符串的公共子序列长度为dp[i][j],注意并不是最长,因为最长是单独用result变量去筛选的。

这样定义是为了后面代码实现方便,其实就是简化了dp数组第一行和第一列的初始化逻辑。详见上一题的博客。

递推公式

本题的递推比较重要,因为要求不连续重复子序列长度,如果当前下标对应的数字相等,那么递推公式和上一题相同;如果当前下标对应的数字不等,也就是存在错位的情况,例如下图所示的例子:

(注意为了方便理解这里dp[i][j]直接写成了对应nums[i]和nums[j])

在这里插入图片描述
像上图这个例子,我们可以看到下标i=4和下标j=0的情况是重复的,这种错位较大的重复情况,也可以通过对dp[i-1][j]dp[i][j-1]进行传递得到

也就是说,如果当前遍历到的下标不相等的话,可以通过传递dp[i-1][j]dp[i][j-1]获取之前错位的部分,相等元素的累积值

完整的递推公式:

int result=0;
for(int i=1;i<=nums.size();i++){
   
    for(int j=1;j<=nums.size();j++){
   
        if(nums[i-1]==nums[j-1]){
   
            //如果相等长度++
            dp[i][j]=dp[i-1][j-1]+1;
        }
        else{
   //如果不相等,直接调取两个错位的累积值
            dp[i][j]=max(dp[i-1][j],dp[i],[j-1]);
        }
        result=max(result,dp[i][j]);
    }
}

初始化

因为本题DP数组的含义依旧是**dp[i][j]代表以下标nums[i-1]数字和下标nums[j-1]数字结尾的字符串最大公共序列长度**,因此初始化全部为0即可,dp[0][j]dp[i][0]都是0。

完整版

class Solution {
   
public:
    int longestCommonSubsequence(string text1, string text2) {
   
        //全部初始化为0
        vector<vector<int>>dp(text1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值