算法训练1-day37-动态规划

27 阅读2分钟
  1. 1143. 最长公共子序列

这道题是公共子序列,因此当字符不相等时,有dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);,而不是归零,因为子序列不要求连续

AC代码:

class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {
        int n = text1.size();
        int m = text2.size();
        // dp[i][j]:长度为i的text1与长度为j的text2的最长公共子序列的长度
        vector<vector<int>> dp(n + 1, vector<int>(m + 1));

        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= m; ++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[n][m];
    }
};
  1. 1035. 不相交的线

1143. 最长公共子序列一样,求最大连线数就是最长的公共子序列,因为相同的子序列有着相同的顺序,其中的各个元素相连也是互不交叉的。

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

明确dp数组定义:以nums[i]结尾的子数组的最大和 因此dp[i]有两个方向可以推出:

  • dp[i - 1] + nums[i],即:nums[i]加入当前连续子序列和
  • nums[i],即:从头开始计算当前连续子序列和 我们还需要一个变量来记录最大和,因为有着最大和的子数组不一定以最后一个数结尾
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int n = nums.size();
        vector<int> dp(n);
        dp[0] = nums[0];
        int res = dp[0];
        for (int i = 1; i < n; ++i) {
            dp[i] = max(nums[i] + dp[i - 1], nums[i]);
            res = max(res, dp[i]);
        }

        return res;
    }
};
  1. 392. 判断子序列1143. 最长公共子序列逻辑类似,只不过最后改为判断得到的长度是否等于t的长度
class Solution {
public:
    bool isSubsequence(string s, string t) {
        int n = s.size();
        int m = t.size();
        vector<vector<int>> dp(n + 1, vector<int>(m + 1));
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= m; ++j) {
                if (s[i - 1] == t[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[n][m] == n;
    }
};