代码随想录训练营第52天|1143.最长公共子序列、1035.不相交的线、53.最大子数组和

文章介绍了如何使用动态规划方法解决最长公共子序列和不相交的线问题,这两个问题都可通过二维数组和相同的递推公式来求解。对于最长公共子序列,dp数组表示两个字符串部分的最长公共子序列长度;对于不相交的线,同样应用此策略找到最大数量的不相交线段。此外,还展示了如何用动态规划解决最大子数组和问题,通过维护以每个位置为结束点的最大子数组和来找到全局最大值。
摘要由CSDN通过智能技术生成

1143.最长公共子序列1035.不相交的线53.最大子数组和

1143.最长公共子序列

对于最长公共子序列,我们可以用二维动态数组进行解决。
我们定义一个二维数组dp行数为text1.size()+1列数为text2.size()+1,dp[ii][jj]表示text1中0-ii-1个元素和text2中0-jj-1个元素中最长的公共子序列。

对于两个数组中的每一个元素都有两种可能,
两个元素相等于或者不相等,如果两个元素相等,那么我们他的最长公共子序列应该等于左上元素(两个数组分别前一个元素对应的最长公共最序列)+1,这样表示可以得到更长的公共序列。
于此同时,如果两个元素不相等,那么这个元素应该更新为二维数组左边和上边的较大者,继承可能存在的最大子序列长度。

动态规划四部曲。
1.dp数组的含义。dp[ii][jj]表示text1中0-ii-1和text2中0-jj-1中最长公共子序列。
2.dp数组的递推公式。

if(text1[ii-1] == text2[jj-1])
                    dp[ii][jj] = dp[ii-1][jj-1]+1;
                else
                    dp[ii][jj] = max(dp[ii-1][jj],dp[ii][jj-1]);

3.dp数组的初始化。我们令所有第一行和第一列的元素全为0,表示,下标0到下标-1的元素最长公共子序列长度为0,便于进行元素的递推。
4.遍历顺序,先遍历text1或者先遍历text2都可以。

代码

class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {
        vector<vector<int>>dp(text1.size()+1,vector<int>(text2.size()+1,0));
        for(int ii =1;ii<text1.size()+1;ii++)
        {
            for(int jj =1;jj<text2.size()+1;jj++)
            {
                if(text1[ii-1] == text2[jj-1])
                    dp[ii][jj] = dp[ii-1][jj-1]+1;
                else
                    dp[ii][jj] = max(dp[ii-1][jj],dp[ii][jj-1]);
            }
        }
        return dp[text1.size()][text2.size()];
    }
};

1035.不相交的线

这道题与上面的题类似,不对,本质一模一样,甚至将数组名改一下提交就能通过。不再过多解释。

代码

class Solution {
public:
    int maxUncrossedLines(vector<int>& text1, vector<int>& text2) {
        vector<vector<int>>dp(text1.size()+1,vector<int>(text2.size()+1,0));
        for(int ii =1;ii<text1.size()+1;ii++)
        {
            for(int jj =1;jj<text2.size()+1;jj++)
            {
                if(text1[ii-1] == text2[jj-1])
                    dp[ii][jj] = dp[ii-1][jj-1]+1;
                else
                    dp[ii][jj] = max(dp[ii-1][jj],dp[ii][jj-1]);
            }
        }
        return dp[text1.size()][text2.size()];
    }
};

53.最大子数组和

对于该题,我们之前利用贪心算法做过一次,此处不再提,将用动态规划的思路进行解决。
我们要求最大的连续子数组和,因此我们可以用dp数组记录以ii-1为结尾的最大子数组和,将首项初始化为最小整数,方便推导后续元素。例如 1 2 -1 -5 3,他们的dp数组即为INT_MIN 1 2 1 -5 3.
因此我们更新dp数组的思路为:如果dp[ii-1]小于零,我们就让dp[ii]=nums[ii-1],不然的话,将让dp[ii]=dp[ii-1]+nums[ii-1]。

动态规划四部曲。
1.dp数组的含义。dp[ii][jj]表示以nums[ii-1]结尾的元素所能表示的最大子数组和。
2.dp数组的递推公式。如上所说,我们的代码为

dp[ii] = max(dp[ii-1],0)+nums[ii-1];

3.dp数组的初始化。我们让dp数组的首元素即为最小的整数即vector<int>dp(nums.size()+1,INT_MIN);
4.遍历顺序。我们从前向后进行遍历。

代码

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        vector<int>dp(nums.size()+1,INT_MIN);
        if(nums.size()==1) return nums[0];
        int result = nums[0];
        for(int ii =1;ii<nums.size()+1;ii++)
            {
                dp[ii] = max(dp[ii-1],0)+nums[ii-1];
                result = max(dp[ii],result);
            }
        return result;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值