day45.动态规划

1035.不相交的线:

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

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

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

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

 

 思路:和最长公共子序列是一样的,由图可见1 4 就是两个数组的最长公共子序列。

class Solution {
public:
    int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2) {
        vector<vector<int>> dp(nums1.size()+1,vector<int>(nums2.size()+1,0));
        
        //确认递推公式
        int res=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.最大子数组和

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

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

 思路:1.贪心法:局部最优推出全局最优,局部最优就是当前两个的和大于0,如果两个和小于0时,将sum重置为0。

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        //1.贪心做法
        //局部最优推出 全局最优
        vector<int> res(nums.size()+1);
        int j=1,i=0;
        int sum=0;
        int count=-INT_MAX;
       for(int i=0;i<nums.size();i++){
            sum+=nums[i];
            count=max(sum,count);
            if(sum<0){
                sum=0;
            }
       }
        return count;
    }
};

2.动态规划:

 思路:定义一个dp数组,这道题目的核心就在于推出递归公式,dp[i]意义在于包括下标i(以nums[i]为结尾)的最大连续子序列和为dp[i]。dp[i]由什么可以推导出来呢,dp[i]取 当前数组的值或者加上当前数组的值 的最大值。定义一个res来取整个数组的最大值。

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        //2.动态规划
        if(nums.size()==0)
        return 0;
        vector<int> dp(nums.size()+1);
        //dp数组的含义是 dp[i] 代表 0-i 区间的 最大子数组和
        dp[0]=nums[0];
        int res=dp[0];
        //dp[i]=dp[i-1]+nums[i];
        for(int i=1;i<nums.size();i++){
           dp[i]=max(nums[i],dp[i-1]+nums[i]);
           res=max(res,dp[i]);
        }

        return res;
    }
};

392.判断子序列

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

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

进阶:

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

致谢:

特别感谢 @pbrother 添加此问题并且创建所有测试用例。

 思路:1.双指针做法,遇到相同的就移动指向字串的指针,当slow等于字串长度时,返回true,否则返回false。

class Solution {
public:
    bool isSubsequence(string s, string t) {
        if(s.size()==0){
            return true;
        }
        int slow=0;
        int fast=0;
        for(slow,fast;fast<t.size();fast++){
            if(s[slow]==t[fast])
            {
                slow++;
                if(slow==s.size()){
                    return true;
                }
            }
        }
        return false;
    }
};

2.动态规划:

 思路: 和最长公共子序列也是蛮像的,不过else的语句里只有dp[i][j-1],没有dp[i-1][j],因为s是子串,不能用子串来判断。 注意 i和j可以等于是,s,size和t.size()  因为  让i可以等于s.size()是为了完整地检查s是否是t的子序列,确保考虑到了s的所有字符与t的不同部分进行匹配的情况。

class Solution {
public:
    bool isSubsequence(string s, string t) {

        vector<vector<int>> dp(s.size()+1,vector<int>(t.size()+1,0));
        if (s.empty()) return true;
        if (t.empty()) return false;
        for(int i=1;i<=s.size();i++){
            for(int j=1;j<=t.size();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[s.size()][t.size()]==s.size()){
            return true;
        }
        return false;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值