day56 最长公共子序列 不相交的线 最大子序和

题目1 1143 最长公共子序列

题目链接  1143 最长公共子序列

题意

返回两个字符串text1和text2的最长公共子序列的长度 若不存在,则返回0

子序列是指原字符相对顺序不改变

动态规划

动规五部曲

1)dp数组及下标i的含义

dp[i][j] 表示以[0,i-1]的text1,[0,j-1]的text2的公共子序列的最长长度

2)dp数组初始化

根据递推公式 dp[i][0]表示text1字符串与空字符串的公共子序列的长度最长是0   dp[i][0] = 0

dp[0][j]表示空字符串与text2字符串的公共子序列的长度最长是0   dp[0][j] = 0

其他下标处的dp[i][j]可以初始化为任意值 因为可以由递推公式求得

3)递推公式

if(text[i-1] == text[j-1])  dp[i][j] = dp[i-1][j-1] + 1;

else dp[i][j] = max(dp[i][j-1], dp[i-1][j]); 

如果不相同的话,考虑两种情况取最大者

1)text1字符串与text2字符串在当前位置的前一个位置进行比较  dp[i][j-1]

2)text2字符串与text1字符串在当前位置的前一个位置进行比较  dp[i-1][j]

4)遍历顺序

根据递推公式,从左到右遍历,从上到下遍历

for(int i = 1; i < text1.size(); i++){

    for(int j = 1;  j < text2.size();  j++)}

5)打印dp数组

代码

class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {
       //定义并初始化dp数组
       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]);
            // cout <<"i = "<< i << " " << "j = " << j << " " << "dp" << dp[i][j] << endl;
        }
       }
       return dp[text1.size()][text2.size()];
    }
};
  • 时间复杂度: O(n * m),其中 n 和 m 分别为 text1 和 text2 的长度
  • 空间复杂度: O(n * m)

题目2 1035 不相交的线

题目链接  :1035 不相交的线

题意

整数数组nums1和nums2中,满足nums1[i] == nums2[j]时,使用直线连接两个数字 。

绘制的直线不与其他连线相交  说明在数组nums1中 找到一个与nums2相同的子序列,只要这个子序列不改变相对顺序,那么连线就不会相交

因此最大连线数就是最长公共子序列的长度  和上题题解一样

代码

class Solution {
public:
    int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2) {
        //定义并初始化dp数组
        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()];
    }
};
  • 时间复杂度: O(n * m)
  • 空间复杂度: O(n * m)

题目3 53 最大子数组和

题目链接  53 最大子数组和

题意

返回整数数组nums中的连续子数组(至少包含一个元素)的最大和  

即 找到连续子序列中和最大的那个

动态规划

动规五部曲

1)dp数组及下标i的含义

dp[i] 表示以nums[i]为结尾的连续数组的最大和

2)dp数组初始化

根据递推公式  dp[0] = nums[0];   其它dp[i]初始化为0

3)递推公式

分两种情况   取最大者

1)延续前面的和    dp[i-1] + nums[i]

2)以当前位置为起点,重新开始    nums[i]

dp[i] = max(dp[i-1]+nums[i],nums[i])

4)遍历顺序

根据递推公式 从前向后遍历  for(int i = 1; i<nums.size(); i++)

注意,最终的最大和不一定包含最后一个元素,所以需要遍历dp数组,找到最大值

5)打印dp数组

代码

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        //定义dp数组  初始化
        vector<int> dp(nums.size(), 0);
        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]);
            result = max(result, dp[i]);
        }
        return result;
    }
};
  • 时间复杂度:O(n)
  • 空间复杂度:O(n)

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-13 20:26:04       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-13 20:26:04       100 阅读
  3. 在Django里面运行非项目文件

    2024-04-13 20:26:04       82 阅读
  4. Python语言-面向对象

    2024-04-13 20:26:04       91 阅读

热门阅读

  1. Python 潮流周刊第 46 期(摘要)+ 赠书 7 本

    2024-04-13 20:26:04       40 阅读
  2. Docker常用命令

    2024-04-13 20:26:04       32 阅读
  3. 【LeetCode热题100】【链表】环形链表 II

    2024-04-13 20:26:04       39 阅读
  4. 使用.cc域名的优势

    2024-04-13 20:26:04       34 阅读
  5. Linux服务器疑似被入侵

    2024-04-13 20:26:04       29 阅读