代码随想录算法训练营第 44 天 |LeetCode1143.最长公共子序列 LeetCode 1035.不相交的线 LeetCode 53. 最大子序和 LeetCode392.判断子序列

代码随想录算法训练营

Day44 代码随想录算法训练营第 44 天 |LeetCode1143.最长公共子序列 LeetCode 1035.不相交的线 LeetCode 53. 最大子序和 LeetCode392.判断子序列



前言

LeetCode1143.最长公共子序列

讲解文档

LeetCode 1035.不相交的线

讲解文档

LeetCode 53. 最大子序和

讲解文档

LeetCode392.判断子序列

讲解文档


一、LeetCode1143.最长公共子序列

1.题目链接

LeetCode1143.最长公共子序列

2.思路

(1)dp[i][j] 表示字符串1[0,i] 和字符串[0,j]的最长公共子序列长度
(2)状态转移:
1)如果text1[i]==text2[j] 说明最长公共子序列延长,text1[i]和text2[j]都加入公共子序列:dp[i][j] = dp[i - 1][j - 1] + 1
2)如果text1[i] != text2[j]说明最新的元素不能同时加入加入最长公共子序列,舍去text1[i] 或者 text2[j]:
字符串1[0,i] 和字符串[0,j]的最长公共子序列长度等于[0,i][0,j-1]公共最长公共子序列的长度与 [0,i-1][0,j]公共最长公共子序列的长度的最大值
(3)初始化
如果text1[0]和text2[j]相等,那么从此以后所有的dp[0][j]都设置为1
如果text1[i]和text2[0]相等,那么从此以后所有的dp[i][0]都设置为1

3.题解

class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {
        int n = text1.size();
        int m = text2.size();
        vector<vector<int>> dp(n, vector<int>(m, 0));
        int flag = 0;
        for (int i = 0; i < n; i++) {
            if (text1[i] == text2[0])
                flag = 1;
            if (flag)
                dp[i][0] = 1;
        }
        flag = 0;
        for (int i = 0; i < m; i++) {
            if (text1[0] == text2[i])
                flag = 1;
            if (flag)
                dp[0][i] = 1;
        }
        for (int i = 0; i < n && i < m; i++) {
            if (text1[i] == text2[i])
                dp[i][i] = 1;
        }
        for (int i = 1; i < n; i++) {
            for (int j = 1; j < m; j++) {
                if (text1[i] == text2[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[n - 1][m - 1];
    }
};

二、LeetCode1035.不相交的线

1.题目链接

LeetCode1035.不相交的线

2.思路

(1)不相交的线:
1)要求:连接两个数字 nums1[i] 和 nums2[j] 的直线,只要 nums1[i] == nums2[j],且直线不能相交
2)直线不能相交—子序列元素相对顺序不变
变成求nums1和nums2的子序列长度,并且子序列元素相对顺序不变

e.g.1 2 4和1 4 2:公共子序列为 1 2

3.题解

class Solution {
public:
    int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2) {
        int n = nums1.size();
        int m = nums2.size();
        vector<vector<int>> dp(n, vector<int>(m, 0));
        int flag = 0;
        for (int i = 0; i < n; i++) {
            if (nums1[i] == nums2[0])
                flag = 1;
            if (flag)
                dp[i][0] = 1;
        }
        flag = 0;
        for (int i = 0; i < m; i++) {
            if (nums1[0] == nums2[i])
                flag = 1;
            if (flag)
                dp[0][i] = 1;
        }
        for (int i = 0; i < n && i < m; i++) {
            if (nums1[i] == nums2[i])
                dp[i][i] = 1;
        }
        for (int i = 1; i < n; i++) {
            for (int j = 1; j < m; j++) {
                if (nums1[i] == nums2[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[n - 1][m - 1];
    }
};

三、LeetCode 53. 最大子序和

1.题目链接

LeetCode53. 最大子序和

2.思路

(1)dp[i] 表示[0,i]的最大连续子序和
(2)状态转移
1)dp[i-1]小于0:[0,i-1]最大连续子序和+nums[i] 比nums[i]自身更小
2)dp[i-1]大等于0:dp[i] = dp[i - 1] + nums[i]
(3)初始化
dp[0]=nums[0]
(4)结果:dp[i]的最大值

3.题解

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int n = nums.size();
        int dp[n];
        dp[0] = nums[0];
        int res = dp[0];
        for (int i = 1; i < nums.size(); i++) {
            if (dp[i - 1] < 0)
                dp[i] = nums[i];
            else
                dp[i] = dp[i - 1] + nums[i];
            if (res < dp[i])
                res = dp[i];
        }
        return res;
    }
};

四、LeetCode392.判断子序列

1.题目链接

LeetCode392.判断子序列

2.思路

(1)dp[i][j] s在[0,i]和t在[0,j]的公共子序列长度
注:这里的公共子序列要求s不能放弃元素,s的元素必须全都加入子序列
(2)转移方程
1)s[i] t[j]相等,则t[j]可以加入子序列 dp[i][j] = dp[i - 1][j - 1] + 1
2)s[i] t[j]不相等,则t[j]不加入子序列,dp[i][j]=dp[i][j-1](只能删除t[j],不能删除s[i])
(3)初始化
只看s[0] 如果有t[j]==s[0] 那么从此以后dp[0][j]均为1

3.题解

class Solution {
public:
    bool isSubsequence(string s, string t) {
        int n = s.size();
        int m = t.size();
        if (n == 0)
            return true;
        if (m == 0)
            return false;
        vector<vector<int>> dp(n, vector(m, 0));
        int flag = 0;
        for (int i = 0; i < m; i++) {
            if (s[0] == t[i])
                flag = 1;
            if (flag)
                dp[0][i] = 1;
        }
        for (int i = 1; i < n; i++) {
            for (int j = 1; j < m; j++) {
                if (s[i] == t[j])
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                else
                    dp[i][j] = dp[i][j - 1]; // 因为只能是t删除元素,在算子序列的时候S必须全保留
            }
        }
        return dp[n - 1][m - 1] == s.size();
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值