• 代码随想录 | Day 53 - LeetCode 1143. 最长公共子序列、LeetCode 1035. 不相交的线、LeetCode 53. 最大子序和


            今天是子序列问题的延续,相对都比较简单。重点一方面是要分清楚与dp[i]对应的子序列是否要以nums[i]结尾,另一方面要判断好两种情况各自对应的dp数组值填充方法。


            第1题(LeetCode 1143. 最长公共子序列)相比day 52中第3题(LeetCode 718. 最长重复子数组),子序列不再要求是连续的,剩余地方都与其一样。这一变化反映在定义上,dp[i][j]就变成了text1[0: i - 1]与text2[0: j - 1]的最长公共子序列长度(不用[0 : i]和[0 : j]的理由与之前一致,避免初始化的麻烦)。

            对于text1[i - 1]与text2[j - 1]相等的情况,最长公共子序列长度相比没有text1[i - 1]和text2[j - 1]时就要增加一位,所以dp[i][j] = dp[i - 1][j - 1] + 1;而两者不相等时,因为子序列不再必须是连续的,所以此时的最大长度不需要归为1,而是维持之前的最大长度即可,之前的最大长度可能是dp[i - 1][j]或dp[i][j - 1],两者中取较大值。初始化方式、遍历顺序都与上一题一样。

    1. class Solution {
    2. public:
    3. int longestCommonSubsequence(string text1, string text2) {
    4. vectorint>> dp(text1.size() + 1, vector<int>(text2.size() + 1, 0));
    5. for (int i = 1; i <= text1.size(); ++i) {
    6. for (int j = 1; j <= text2.size(); ++j) {
    7. if (text1[i - 1] == text2[j - 1]) { // 不是text1[i] == text2[j]
    8. dp[i][j] = dp[i - 1][j - 1] + 1;
    9. }
    10. else {
    11. dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
    12. }
    13. }
    14. }
    15. return dp[text1.size()][text2.size()];
    16. }
    17. };

            实现中需要注意,因为为了初始化的方便而采用了额外多一行、一列的dp矩阵,所以与dp[i][j]对应的是text1[i - 1]和text2[j - 1]是否想等的判断,而不是text1[i]和text2[j]。


            第2题(LeetCode 1035. 不相交的线)中,“nums1[i] == nums2[j]”要求相等,“绘制的直线不与任何其他连线(非水平线)相交”要求有序,既相等又有序的要求就跟第1题是完全一样的。所以将这一题中的nums1、nums2分别看作第1题中的text1、text2即可,思路和实现完全一样。

    1. class Solution {
    2. public:
    3. int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2) {
    4. vectorint>> dp(nums1.size() + 1, vector<int>(nums2.size() + 1, 0));
    5. for (int i = 1; i <= nums1.size(); ++i) {
    6. for (int j = 1; j <= nums2.size(); ++j) {
    7. if (nums1[i - 1] == nums2[j - 1]) {
    8. dp[i][j] = dp[i - 1][j - 1] + 1;
    9. }
    10. else {
    11. dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
    12. }
    13. }
    14. }
    15. return dp[nums1.size()][nums2.size()];
    16. }
    17. };

            第3题(LeetCode 53. 最大子序和)在day 31中用贪心方法解决过,这里再用DP尝试。dp数组定义方面,将dp[i]定义为“以nums[i]结尾的连续子数组的最大和”。那么对于nums[i],就有两种选择。第1种是将自己拼接在前面的连续子数组之后,得到新的和dp[i - 1] + nums[i];第2种则是抛弃掉前面的连续子数组,从当前位置重新开始,得到新的和nums[i]。从这两种选择中取较大值作为当前位置的dp数值。而题目所求的“连续子数组的最大和”可能以任意位置的数字结尾,所以要在中途不断记录dp数组的最大值,作为最后的结果返回。

    1. class Solution {
    2. public:
    3. int maxSubArray(vector<int>& nums) {
    4. int dp[nums.size()];
    5. dp[0] = nums[0];
    6. int ans = nums[0]; // nums[0]也可以初始化为INT_MIN
    7. for (int i = 1; i < nums.size(); ++i) {
    8. dp[i] = max(dp[i - 1] + nums[i], nums[i]);
    9. ans = max(ans, dp[i]);
    10. }
    11. return ans;
    12. }
    13. };
  • 相关阅读:
    深入解析HTTP请求:了解请求特征与报文格式的关键秘密
    CentOS7 安装Jenkins 2.414.3 详细教程
    Java虚拟机底层原理分析
    ElasticStack日志分析平台-ES 集群、Kibana与Kafka
    Spring Boot 配置 Knife4j
    【CSS3】CSS3 3D 转换 ① ( CSS3 3D 转换简介 | 3D 物体与 2D 物体区别 | 3D 空间坐标系 | 常用的 3D 转换属性 | 3D 位移转换语法 | 代码示例 )
    Mysql中获取所有表名以及表名带时间字符串使用BetweenAnd筛选区间范围
    4.外部协作单位的组织与管理
    C++的类型转换
    【Python】这篇文章能让你明白经验模态分解(EMD)——EMD在python中的实现方法
  • 原文地址:https://blog.csdn.net/weixin_43469527/article/details/127876879