「代码随想录算法训练营」第三十八天 | 动态规划 part11

1143. 最长公共子序列

题目链接:https://leetcode.cn/problems/longest-common-subsequence/
文章讲解:https://programmercarl.com/1143.最长公共子序列.html
题目难度:中等
视频讲解:https://www.bilibili.com/video/BV1ye4y1L7CQ
题目状态:有点思路,但细节有点混乱

思路:

维护一个二维动规数组dp[i][j],用来记录长度为i-1的字符串text1与长度为j-1的字符串text2的最长公共子序列,它的更新条件如下:

  • 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])

其中为什么是i-1和j-1,这个问题和上一题是一样的。

代码:

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

1035. 不相交的线

题目链接:https://leetcode.cn/problems/uncrossed-lines/
文章讲解:https://programmercarl.com/1035.不相交的线.html
题目难度:中等
视频讲解:https://www.bilibili.com/video/BV1h84y1x7MP
题目状态:看题解

思路:

其本质就是寻找最长公共子序列,也就是上一题。

代码:

class Solution {
public:
    int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2) {
        int len1 = nums1.size();
        int len2 = nums2.size();
        vector<vector<int>> dp(len1 + 1, vector<int>(len2 + 1, 0));
        for(int i = 1; i <= len1; ++i) {
            for(int j = 1; j <= len2; ++j) {
                if(nums1[i - 1] == nums2[j - 1]) dp[i][j] = dp[i - 1][j - 1] + 1;
                else dp[i][j] = max(dp[i][j - 1], dp[i - 1][j]);
            }
        }
        return dp[len1][len2];
    }
};

53. 最大子数组和

题目链接:https://leetcode.cn/problems/maximum-subarray/
文章讲解:https://programmercarl.com/0053.最大子序和(动态规划).html
题目难度:中等
视频讲解:https://www.bilibili.com/video/BV19V4y1F7b5
题目状态:之前使用其他方法AC过

思路一:贪心算法

遍历整体数组,记录当前总和count,若count出现了负数,说明前面这些数组都可以删掉,从下一个元素开始重新遍历,最终返回最大的count值。

代码一:

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

思路二:动态规划

维护一个一维动规数组dp[i]表示以i元素结尾的最大值(注意是以i元素结尾的,而并不是整体的最大值,整体最大值还需要再去遍历)。

代码二:

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

392. 判断子序列

题目链接:https://leetcode.cn/problems/is-subsequence/
文章讲解:https://programmercarl.com/0392.判断子序列.html
题目难度:简单
视频讲解:https://www.bilibili.com/video/BV1tv4y1B7ym/
题目状态:使用其他方式通过,没有使用动规

思路一:

使用两个指针ij分别遍历题目中的序列st,若遇到s[i] == t[j],则i++,最后判断i的位置,如果i最后的位置是序列s的末尾,表示s遍历完了,也就是说在t中找到了所有的s

代码一:

class Solution {
public:
    bool isSubsequence(string s, string t) {
        if(s.empty()) return true;
        if(t.empty()) return false;
        int i = 0, j = 0;
        while(i < s.size() && j < t.size()) {
            if(s[i] == t[j]) i++;
            j++;
        }
        return i == s.size();
    }
};

思路二:动态规划

维持一个二维动规数组dp[i][j]表示在序列s遍历到i - 1,序列t遍历到j - 1时,这两者的相同子序列的长度。

  • s[i - 1] == t[j - 1]时,动规数组将在前面的基础上加1
  • 当两者不相等的时候,动规数组维持原状

代码二:

class Solution {
public:
    bool isSubsequence(string s, string t) {
        int sLen = s.size();
        int tLen = t.size();
        vector<vector<int>> dp(sLen + 1, vector<int>(tLen + 1, 0));
        for(int i = 1; i <= sLen; ++i) {
            for(int j = 1; j <= tLen; ++j) {
                if(s[i - 1] == t[j - 1]) dp[i][j] = dp[i - 1][j - 1] + 1;
                else dp[i][j] = dp[i][j - 1];
            }
        }
        if(dp[sLen][tLen] == sLen) return true;
        else return false;
    }
};
posted @ 2024-08-15 08:03  云雀AC了一整天  阅读(16)  评论(0编辑  收藏  举报