718/1143/53/392

文章介绍了使用动态规划解决编程问题,包括寻找最长重复子数组的长度、最长公共子序列的计算以及判断一个字符串是否为另一个字符串的子序列。还提及了贪心算法在最大子序和问题中的应用。
摘要由CSDN通过智能技术生成

718.最长重复子数组

class Solution {
public:
    int findLength(vector<int>& A, vector<int>& B) {
//动态规划,从后往前
//[i:]与[j:]的最长公共前缀
/*
dp[i][j] 的值从 dp[i + 1][j + 1] 转移得到,
首先计算 dp[len(A) - 1][len(B) - 1],最后计算 dp[0][0]。
*/
    int n=A.size(),m=B.size();
    vector<vector<int>> dp(n+1,vector<int>(m+1,0));
    int ans=0;
    for(int i=n-1;i>=0;i--){
        for(int j=m-1;j>=0;j--){
            //对应位置比较
            dp[i][j] = A[i]==B[j] ?dp[i+1][j+1]+1:0;
            ans=max(ans,dp[i][j]);
        }
    }
    return ans;
    }
};

1143.最长公共子序列

dp数组方便后面的数据就行计算,i从1开始,j从1开始,那么表示的是str1[i-1]范围内的字符。

class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {
        int m = text1.length();
        int n = text2.length();
        //dp[0][j],dp[i][0]没有意义
        vector<vector<int>> dp(m+1,vector<int>(n+1,0));
        //对比字符串
        for(int i = 1;i<=m;i++){
            char c1 = text1.at(i-1);
            for(int j=1;j<=n;j++){
                char c2 = text2.at(j-1);
                if(c1 == c2)
                {
                    dp[i][j] = dp[i-1][j-1]+1;
                }else{
                    //如果不相等的化,那么最大值可能来自于两种情况
                    dp[i][j] =  max(dp[i-1][j],dp[i][j-1]);
                }
            }
        }
        return dp[m][n];
    }
};

53.最大子序和

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

dp[i]:表示以i结尾的子序列的和

1.延续和 2.重新开始计算

dp[i-1]+nums[i],nums[i]

dp[0]=nums[0]

动态规划:

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

贪心算法:

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
    //局部最优的情况下,并记录最大的“连续和”,可以推出全局最优。
    int result = INT32_MIN;
    int count = 0;
    for(int i=0;i<nums.size();i++){
        count +=nums[i];
        //不断更新和
        if(count>result){
            result = count;
        }
        //丢弃前面的负数,直接从0开始
        if(count<0) count = 0;
    }
    return result;
    }
};

392.判断子序列

二维数组表示

最长公共子序列的长度等于s的长度

s一定要包含在t中的

  1. 确定递推公式

在确定递推公式的时候,首先要考虑如下两种操作,整理如下:

  • if (s[i - 1] == t[j - 1])
    • t中找到了一个字符在s中也出现了
  • if (s[i - 1] != t[j - 1])
    • 相当于t要删除元素,继续匹配

if (s[i - 1] == t[j - 1]),那么dp[i][j] = dp[i - 1][j - 1] + 1;,因为找到了一个相同的字符,相同子序列长度自然要在dp[i-1][j-1]的基础上加1(如果不理解,在回看一下dp[i][j]的定义

if (s[i - 1] != t[j - 1]),此时相当于t要删除元素,t如果把当前元素t[j - 1]删除,那么dp[i][j] 的数值就是 看s[i - 1]与 t[j - 2]的比较结果了,即:dp[i][j] = dp[i][j - 1];

class Solution {
public:
    bool isSubsequence(string s, string t) {
        vector<vector<int>> dp(s.size() + 1, vector<int>(t.size() + 1, 0));
        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];//如果t[j-1]位置不匹配,那就等于s和t[j-2]的匹配个数
            }
        }
        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、付费专栏及课程。

余额充值