代码训练营 day49|LeetCode 1143,LeetCode 1035,LeetCode 53,LeetCode 392

时间:2024-10-30 21:50:57

前言

这里记录一下陈菜菜的刷题记录,主要应对25秋招、春招
个人背景
211CS本+CUHK计算机相关硕,一年车企软件开发经验
代码能力:有待提高
常用语言:C++

系列文章目录

第49天 :第九章 动态规划part11


`

文章目录

  • 前言
  • 系列文章目录
    • 第49天 :第九章 动态规划part11
  • 一、今日任务
  • 二、详细布置
      • 1143.最长公共子序列
        • 提示:
        • 样例1:
        • 思路
        • 实战
      • 1035.不相交的线
        • 提示:
        • 样例1:
        • 思路
        • 实战
      • 53. 最大子序和
        • 提示:
        • 样例1:
        • 样例2:
        • 思路
        • 实战
      • 392.判断子序列
        • 提示:
        • 样例1:
        • 样例2:
        • 思路
        • 实战
        • 踩坑
    • 总结



一、今日任务

● 1143.最长公共子序列
● 1035.不相交的线
● 53. 最大子序和
● 392.判断子序列

二、详细布置

1143.最长公共子序列

题目链接:力扣1143
文章讲解:代码随想录

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

一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。

例如,“ace” 是 “abcde” 的子序列,但 “aec” 不是 “abcde” 的子序列。
两个字符串的 公共子序列 是这两个字符串所共同拥有的子序列。

提示:

1 <= text1.length, text2.length <= 1000
text1 和 text2 仅由小写英文字符组成。

样例1:
输入:text1 = "abcde", text2 = "ace" 
输出:3  
解释:最长公共子序列是 "ace" ,它的长度为 3
思路

这题跟昨天最后一题很像,区别在于这个子串不需要连续。

实战
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.不相交的线

题目链接:力扣1035题链接
文章讲解:图文讲解

在两条独立的水平线上按给定的顺序写下 nums1 和 nums2 中的整数。

现在,可以绘制一些连接两个数字 nums1[i] 和 nums2[j] 的直线,这些直线需要同时满足:

nums1[i] == nums2[j]
且绘制的直线不与任何其他连线(非水平线)相交。
请注意,连线即使在端点也不能相交:每个数字只能属于一条连线。

以这种方法绘制线条,并返回可以绘制的最大连线数。

提示:

1 <= nums1.length, nums2.length <= 500
1 <= nums1[i], nums2[j] <= 2000

样例1:
输入:nums1 = [1,4,2], nums2 = [1,2,4]
输出:2
解释:可以画出两条不交叉的线,如上图所示。 
但无法画出第三条不相交的直线,因为从 nums1[1]=4 到 nums2[2]=4 的直线将与从 nums1[2]=2 到 nums2[1]=2 的直线相交。   
思路

这题和上一题一样,子串的相对顺序一样,所以就不会交叉。

实战
class Solution {
public:
    int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2) {
        vector<vector<int>> dp(nums1.size()+1,vector<int>(nums2.size()+1,0));
        for(int i=1;i<=nums1.size();i++){
            for(int j=1;j<=nums2.size();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[nums1.size()][nums2.size()];
    }
};

53. 最大子序和

题目链接:LeetCode53
文章讲解:图文讲解

题目描述

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

子数组
是数组中的一个连续部分。

提示:

1 <= nums.length <= 105
-104 <= nums[i] <= 104

样例1:
输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 
样例2:
输入:nums = [1]
输出:1
思路

这个动态规划只涉及前一个状态,取前一个状态+这个位置的值和这个位置本身的值最大的作为最大和。

实战
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
    /*    //贪心
        vector<int> weight(nums.size(),0);
        if(nums.size()<=1)
            return nums[0];
        weight[0]=nums[0];
        for(int i=1;i<nums.size();i++){
            weight[i]=weight[i-1]+nums[i];
            if(weight[i]<=0)
                weight[i]=0;
        }
        int max=INT32_MIN;
        for(int i=0;i<weight.size();i++){
            if(weight[i]>max){
                max=weight[i];
            }
        }
        return max;
    */
    //dp
        if (nums.size() == 0) return 0;
        if (nums.size() == 1) return nums[0];
        vector<int> dp(nums.size(),0);
        dp[0]=nums[0];
        int maxsum=dp[0];
        for(int j=1;j<nums.size();j++){
                dp[j]=max(nums[j],dp[j-1]+nums[j]);
                if(dp[j]>maxsum)
                    maxsum=dp[j];
        }
        return maxsum;
    }
};

392.判断子序列

题目链接:LeetCode392
文章讲解:图文讲解

题目描述

给定字符串 s 和 t ,判断 s 是否为 t 的子序列。

字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。

进阶:

如果有大量输入的 S,称作 S1, S2, … , Sk 其中 k >= 10亿,你需要依次检查它们是否为 T 的子序列。在这种情况下,你会怎样改变代码?

提示:

0 <= s.length <= 100
0 <= t.length <= 10^4
两个字符串都只由小写字符组成。

样例1:
输入:s = "abc", t = "ahbgdc"
输出:true
样例2:
输入:s = "axc", t = "ahbgdc"
输出:false
思路

这个动态规划跟最长子串思路一样,只要最后一个元素的值——表明匹配到最后公共子串的长度,等于子串长度,说明全都匹配得上。

实战
class Solution {
public:
    bool isSubsequence(string s, string t) {
        /*if(s.size()>t.size()||t.size()==0)
            return false;
        if(s.size()==0)
            return true;   */ 
        vector<vector<int>> dp(t.size()+1,vector<int>(s.size()+1,0));
        for(int i=1;i<=t.size();i++){
            for(int j=1;j<=s.size();j++){
                if(t[i-1]==s[j-1])
                    dp[i][j]=dp[i-1][j-1]+1;
                else
                    dp[i][j]=dp[i-1][j];
            }
        }
        if(dp[t.size()][s.size()]==s.size())
            return true;
        return false;
    }
};
踩坑

注释掉的提前判断会影响一个奇怪的例子,导致不通过

总结

今天主要学习了子串的一系列操作,子串问题的模板就是dp[i-1][j-1]表示A串以i-1结尾的子串,和B串以j-1结尾的子串最大公共子串(连续/不连续)长度。
加油,坚持打卡的第49天。