代码随想录算法训练营第五十七天_第九章_动态规划 | 1143.最长公共子序列、1035.不相交的线、53. 最大子数组和 动态规划

LeetCode 1143.最长公共子序列

给定两个字符串 text1 和 text2,返回这两个字符串的最长公共子序列的长度。

视频讲解https://www.bilibili.com/video/BV1ye4y1L7CQ文章讲解https://programmercarl.com/1143.%E6%9C%80%E9%95%BF%E5%85%AC%E5%85%B1%E5%AD%90%E5%BA%8F%E5%88%97.html

  • 思路:
    • dp数组含义:
      • dp[i][j]:text1的子串[0, i - 1]text2的子串[0, j - 1] 的最长公共子序列的长度
    • 递推公式:
      • text1[i - 1] 与 text2[j - 1]相同:dp[i][j] = dp[i - 1][j - 1] + 1;
      • text1[i - 1] 与 text2[j - 1]不同:dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
    • 初始化:全0
      • test1[0, i-1]和空串的最长公共子序列是0dp[i][0] = 0
      • 同理dp[0][j] = 0
    • 遍历顺序:从上到下,从左到右
    • 最终结果:dp[text1.size()][text2.size()]
  • 代码:
class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {
        vector> dp(text1.size() + 1, vector(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()];
    }
};

LeetCode 1035.不相交的线

        我们在两条独立的水平线上按给定的顺序写下 A 和 B 中的整数。现在,我们可以绘制一些连接两个数字 A[i] 和 B[j] 的直线,只要 A[i] == B[j],且我们绘制的直线不与任何其他连线(非水平线)相交。以这种方法绘制线条,并返回我们可以绘制的最大连线数。

视频讲解https://www.bilibili.com/video/BV1h84y1x7MP文章讲解https://programmercarl.com/1035.%E4%B8%8D%E7%9B%B8%E4%BA%A4%E7%9A%84%E7%BA%BF.html

  • 思路:最大不相交连线数最长公共子序列的长度
  • 代码:
class Solution {
public:
    int maxUncrossedLines(vector& A, vector& B) {
        vector> dp(A.size() + 1, vector(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()];
    }
};

LeetCode 53. 最大子数组和(动态规划)

        给定一个整数数组 nums ,找到一个具有最大和的子数组(子数组最少包含一个元素),返回其最大和。子数组 是数组中的一个连续部分。

视频讲解https://www.bilibili.com/video/BV19V4y1F7b5文章讲解https://programmercarl.com/0053.%E6%9C%80%E5%A4%A7%E5%AD%90%E5%BA%8F%E5%92%8C%EF%BC%88%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92%EF%BC%89.html

  • 思路:
    • dp数组含义:
      • dp[i]:以nums[i]结尾的最大子数组和
    • 递推公式:dp[i] = max(dp[i - 1] + nums[i], nums[i]);
    • 初始化:dp[0] = nums[0]
    • 遍历顺序:从前向后
    • 最终结果:dp数组的最大值
  • 代码:
class Solution {
public:
    int maxSubArray(vector& nums) {
        if (nums.size() == 0) return 0;
        vector 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;
    }
};
// 时间复杂度:O(n)
// 空间复杂度:O(n)

你可能感兴趣的:(动态规划,leetcode)