代码随想录算法训练营29期Day57|LeetCode 1143,1035,53

文档讲解:最长公共子序列 不相交的线 最大子序和

1143.最长公共子序列

题目链接https://leetcode.cn/problems/longest-common-subsequence/description/

思路:

设dp[i][j]:长度为[0, i - 1]的字符串text1与长度为[0, j - 1]的字符串text2的最长公共子序列为dp[i][j]。

主要就是两大情况: text1[i - 1] 与 text2[j - 1]相同,text1[i - 1] 与 text2[j - 1]不相同

如果text1[i - 1] 与 text2[j - 1]相同,那么找到了一个公共元素,所以dp[i][j] = dp[i - 1][j - 1] + 1;

如果text1[i - 1] 与 text2[j - 1]不相同,那就看看text1[0, i - 2]与text2[0, j - 1]的最长公共子序列 和 text1[0, i - 1]与text2[0, j - 2]的最长公共子序列,取最大的。

即:dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);

先看看dp[i][0]应该是多少呢?

test1[0, i-1]和空串的最长公共子序列自然是0,所以dp[i][0] = 0;

同理dp[0][j]也是0。

核心代码:

cpp 复制代码
class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {
        vector<vector<int>> dp(text1.size() + 1, vector<int>(text2.size() + 1, 0));
        for (int i = 1; i <= text1.size(); i++) {
            for (int j = 1; j <= text2.size(); j++) {
                if (text1[i - 1] == text2[j - 1]) {
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                } else {
                    dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
                }
            }
        }
        return dp[text1.size()][text2.size()];
    }
};

1035.不相交的线

题目链接: https://leetcode.cn/problems/uncrossed-lines/description/

思路:

本题说是求绘制的最大连线数,其实就是求两个字符串的最长公共子序列的长度!

所以照着上道题做就行了。

核心代码:

cpp 复制代码
class Solution {
public:
    int maxUncrossedLines(vector<int>& A, vector<int>& B) {
        vector<vector<int>> dp(A.size() + 1, vector<int>(B.size() + 1, 0));
        for (int i = 1; i <= A.size(); i++) {
            for (int j = 1; j <= B.size(); j++) {
                if (A[i - 1] == B[j - 1]) {
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                } else {
                    dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
                }
            }
        }
        return dp[A.size()][B.size()];
    }
};

53.最大子序和

题目链接: https://leetcode.cn/problems/maximum-subarray/description/

思路:

dp[i]:包括下标i(以nums[i]为结尾)的最大连续子序列和为dp[i]

dp[i]只有两个方向可以推出来:

dp[i - 1] + nums[i],即:nums[i]加入当前连续子序列和

nums[i],即:从头开始计算当前连续子序列和

一定是取最大的,所以dp[i] = max(dp[i - 1] + nums[i], nums[i]);

从递推公式可以看出来dp[i]是依赖于dp[i - 1]的状态,dp[0]就是递推公式的基础。

根据dp[i]的定义,很明显dp[0]应为nums[0],即dp[0] = nums[0]。

我们要找最大的连续子序列,找每一个i为终点的连续最大子序列即可。

核心代码:

cpp 复制代码
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        if (nums.size() == 0) return 0;
        vector<int> dp(nums.size());
        dp[0] = nums[0];
        int result = dp[0];
        for (int i = 1; i < nums.size(); i++) {
            dp[i] = max(dp[i - 1] + nums[i], nums[i]); // 状态转移公式
            if (dp[i] > result) result = dp[i]; // result 保存dp[i]的最大值
        }
        return result;
    }
};

今日总结

这次的题学习时长1h,以前做过类似的。

快返校了,接着论文idea,头大。

相关推荐
じ☆冷颜〃2 小时前
黎曼几何驱动的算法与系统设计:理论、实践与跨领域应用
笔记·python·深度学习·网络协议·算法·机器学习
数据大魔方2 小时前
【期货量化实战】日内动量策略:顺势而为的短线交易法(Python源码)
开发语言·数据库·python·mysql·算法·github·程序员创富
POLITE32 小时前
Leetcode 23. 合并 K 个升序链表 (Day 12)
算法·leetcode·链表
fpcc3 小时前
C++编程实践——链式调用的实践
c++
楚来客3 小时前
AI基础概念之八:Transformer算法通俗解析
人工智能·算法·transformer
Echo_NGC22373 小时前
【神经视频编解码NVC】传统神经视频编解码完全指南:从零读懂 AI 视频压缩的基石
人工智能·深度学习·算法·机器学习·视频编解码
会员果汁3 小时前
leetcode-动态规划-买卖股票
算法·leetcode·动态规划
橘颂TA4 小时前
【剑斩OFFER】算法的暴力美学——二进制求和
算法·leetcode·哈希算法·散列表·结构与算法
bkspiderx5 小时前
C++中的volatile:从原理到实践的全面解析
开发语言·c++·volatile