【动态规划】两个数组问题

这篇具有很好参考价值的文章主要介绍了【动态规划】两个数组问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

动态规划(两个数组问题)

1. 最长公共子序列

题目链接

  1. 状态表示

    dp[i][j] 表示 s1 0 到 i 区间内,以及时s2 0 到 j 区间内所有的子序列中,最长的公共子序列

  2. 状态转移方程

    根据最后一个位置的请款分类讨论。

    【动态规划】两个数组问题,动态规划,算法

  3. 初始化

    关于字符串的dp问题,空串是有研究意义的。引入空串的概念之后会方便我们的初始化

    这里还可以使用之前的方法,使用辅助节点的方式

  4. 填表顺序

    从下往上,从左到右

  5. 返回值

AC代码:文章来源地址https://www.toymoban.com/news/detail-681323.html

class Solution 
{
public:
    int longestCommonSubsequence(string text1, string text2) 
    {
        int n = text1.size();
        int m = text2.size();
        vector<vector<int>> dp(n + 1, vector<int>(m + 1));
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= m; 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[n][m];
    }
};

2. 不相交的线

题目链接

题目分析:根据这个题目可以看到不就是找最长公共子序列嘛

  1. 状态表示

    dp[i][j] 表示 0 到 i 的所有子序列以及 0 到 j 的所有子序列当中,最长的公共子序列

  2. 状态转移方程

    【动态规划】两个数组问题,动态规划,算法

  3. 初始化

  4. 填表

  5. 返回值

AC代码:

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

3. 不同的子序列

题目链接

  1. 状态表示

    dp[i][j] 表示 0 到 j 之间的所有子序列中有多少个出现 目标中0 到 i 之间的字母

  2. 状态转移方程

    【动态规划】两个数组问题,动态规划,算法

  3. 初始化

  4. 填表

  5. 返回值

AC代码:

class Solution 
{
public:
    int numDistinct(string s, string t) 
    {
        int n = s.size();
        int m = t.size();
        vector<vector<double>> dp(m + 1, vector<double>(n + 1));
        for (int i = 0; i <= n; i++) dp[0][i] = 1;
        for (int i = 1; i <= m; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                dp[i][j] += dp[i][j - 1];
                if (s[j - 1] == t[i - 1]) dp[i][j] += dp[i - 1][j - 1];
            }
        }
        return dp[m][n];
    }
};

4. 交错字符串

题目链接

  1. 状态表示

    dp[i][j] 表示 s1中[1, i]之间的字符串,以及s2当中[1,j]之间的字符串能否拼接成s3当中[1, i + j]之间的字符串

  2. 状态转移方程

    【动态规划】两个数组问题,动态规划,算法

  3. 初始化

    当两个字符串都是空的时候,返回的一定是true,当s1 不为空, s2 为空,只要s1有一个不等于s3则直接返回false否则为true

    s2的初始化也一样

  4. 填表

    从上到下,从左到右

  5. 返回值

AC代码:

class Solution 
{
public:
    bool isInterleave(string s1, string s2, string s3) 
    {
        int m = s1.size();
        int n = s2.size();
        if (m + n != s3.size()) return false;
        s1 = " " + s1;
        s2 = " " + s2;
        s3 = " " + s3;
        vector<vector<bool>> dp(m + 1, vector<bool>(n + 1));
        dp[0][0] = true;
        for (int i = 1; i <= n; i++) 
        {
            if (s2[i] == s3[i]) dp[0][i] = true;
            else break;
        }
        for (int i = 1; i <= m; i++) 
        {
            if (s1[i] == s3[i]) dp[i][0] = true;
            else break;
        }
        for (int i = 1; i <= m; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                if ((s1[i] == s3[i + j] && dp[i - 1][j]) || (s2[j] == s3[i + j] && dp[i][j - 1]))
                    dp[i][j] = true;
            }
        }
        return dp[m][n];
    }
};

5. 两个字符串的最小ASCII和

题目链接

  1. 状态表示

    分析,这个题目要找两个字符串最小的,可以找到公共最大的然后反向求

    dp[i][j] 表示 [0, i] 以及[0, j]的所有子序列当中,ASCII最大的公共子序列的和

  2. 状态转移方程

    【动态规划】两个数组问题,动态规划,算法

  3. 初始化

    无需初始化

  4. 填表

    从左到右,从上到下

  5. 返回值

    两个字符串的和前去最大的乘以2

AC代码:

class Solution 
{
public:
    int minimumDeleteSum(string s1, string s2) 
    {
        int m = s1.size();
        int n = s2.size();
        vector<vector<int>> dp(m + 1, vector<int>(n + 1));
        for (int i = 1; i <= m; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                dp[i][j] = max(dp[i][j - 1], dp[i - 1][j]);
                if (s1[i - 1] == s2[j - 1])
                {
                    dp[i][j] = max(dp[i][j], dp[i - 1][j - 1] + s1[i - 1]);
                }
            }
        }
        int sum = 0;
        for (auto e : s1) sum += e;
        for (auto e : s2) sum += e;
        return sum - dp[m][n] - dp[m][n];
    }
};

6. 最长重复子数组

题目链接

  1. 状态表示

    dp[i][j]以 i 位置为结尾的所有子数组,以及以j 位置为结尾的所有子数组当中,最长公共子数组的长度

  2. 状态转移方程

    【动态规划】两个数组问题,动态规划,算法

  3. 初始化

    无需初初始化

  4. 填表

  5. 返回值

AC代码:

class Solution 
{
public:
    int findLength(vector<int>& nums1, vector<int>& nums2) 
    {
        int m = nums1.size();
        int n = nums2.size();
        vector<vector<int>> dp(m + 1, vector<int>(n + 1));
        int ret = 0;
        for (int i = 1; i <= m; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                if (nums1[i - 1] == nums2[j - 1]) 
                {
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                }
                ret = max(ret, dp[i][j]);
            }
        }
        return ret;
    }
};

7. 通配符匹配

题目链接

  1. 状态表示

    dp[i][j] 表示 p[0, j]区间内子串能否匹配s[0, i]区间内的子串

  2. 状态转移方程

    【动态规划】两个数组问题,动态规划,算法

    这种有很多表示方法的状态转移方程,需要优化不可能把每个状态都表示出来

    第一种就是采用数学方法来优化:

    【动态规划】两个数组问题,动态规划,算法

    还可以根据状态表示以及实际情况优化状态转移方程

    【动态规划】两个数组问题,动态规划,算法

  3. 初始化

    p[0][j] == ”*“ 时就一直是true

  4. 填表

  5. 返回值

AC代码:

class Solution 
{
public:
    bool isMatch(string s, string p) 
    {
        int m = s.size();
        int n = p.size();
        s = " " + s, p = " " + p;
        vector<vector<bool>> dp(m + 1, vector<bool>(n + 1));
        dp[0][0] = true;
        for (int j = 1; j <= n; j++)
        {
            if (p[j] == '*') dp[0][j] = true;
            else break;
        }
        for (int i = 1; i <= m; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                if (p[j] == '*') 
                    dp[i][j] = dp[i- 1][j] || dp[i][j - 1];
                else if (p[j] == '?') dp[i][j] = dp[i - 1][j - 1];
                else 
                {
                    if (s[i] == p[j]) dp[i][j] = dp[i - 1][j - 1];
                }
            }
        }
        return dp[m][n];
    }
};

到了这里,关于【动态规划】两个数组问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 动态规划课堂7-----两个数组的dp问题(等价代换)

    目录 引言: 例题1:最长公共子序列 例题2:不同的子序列 例题3:通配符匹配 例题4:正则表达式 结语: 本节我们就要进入 两个数组的dp问题 的学习,通过前面几个章节的学习,相信友友们对动态规划的解题步骤和代码编写步骤已经有了一定的了解(*/ω\*),接下来我会通过

    2024年03月22日
    浏览(29)
  • 算法沉淀——动态规划篇(子数组系列问题(下))

    几乎所有的动态规划问题大致可分为以下5个步骤,后续所有问题分析都将基于此 1.、状态表示:通常状态表示分为以下两种,其中更是第一种为主。 以i为结尾 ,dp[i] 表示什么,通常为代求问题(具体依题目而定) 以i为开始 ,dp[i]表示什么,通常为代求问题(具体依题目而

    2024年04月14日
    浏览(41)
  • 两个数组的动态规划——最长公共子序列模型

    1.考虑空串,即dp表多出一行一列, 代表某个字符串为空。 2.考虑最后一个位置;是否相等; 3.可在字符串最前面加虚拟位置以对应映射关系; 4.一般横行是j,列是i。此时第一行代表第二个字符串不为空,即第一个字符串是空的 给你两个字符串  s   和  t  ,统计并返回在

    2024年03月10日
    浏览(57)
  • 3.数组算法、动态规划

    Array是一个容器,可以容纳固定数量的项目,这些项目应该是相同的类型。大多数数据结构都使用数组来实现其算法。以下是理解Array概念的重要术语。 元素 - 存储在数组中的每个项称为元素。 索引 - 数组中元素的每个位置都有一个数字索引,用于标识元素。 可以使用不同语

    2024年02月16日
    浏览(30)
  • 蓝桥杯-动态规划-子数组问题

    目录 一、乘积最大数组 二、乘积为正数的最长子数组长度 三、等差数列划分 四、最长湍流子数组 心得: 最重要的还是状态表示,我们需要根据题的意思,来分析出不同的题,不同的情况,来分析需要多少个状态 乘积最大数组 1.状态表示 dp[i]:到达i位置的最大乘积子数组。

    2024年02月05日
    浏览(26)
  • c++ 子数组动态规划问题

    1.最大子数组和   力扣 给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 子数组 是数组中的一个连续部分。 示例 1: 示例 2: 示例 3: 2.环形子数组最大和 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 给

    2024年02月12日
    浏览(27)
  • 动态规划——数塔问题(三维数组的应用)

    声明:理论指导《算法设计与分析 第四版》 因为这个地方用到了三维数组,感觉很有意思就故意挑出来分享给大家(三维数组可以看成很多页二维数组) 4.5.1认识动态规划 数塔问题: 如图4-12所示的一个数塔,从顶层到底层或从底层到顶层,在每一结点可以选择向左走或是

    2024年02月03日
    浏览(26)
  • 【动态规划】【数学】【C++算法】805 数组的均值分割

    视频算法专题 动态规划汇总 数学 给定你一个整数数组 nums 我们要将 nums 数组中的每个元素移动到 A 数组 或者 B 数组中,使得 A 数组和 B 数组不为空,并且 average(A) == average(B) 。 如果可以完成则返回true , 否则返回 false 。 注意:对于数组 arr , average(arr) 是 arr 的所有元素的和

    2024年02月20日
    浏览(33)
  • 从二维数组到一维数组——探索01背包问题的动态规划优化

    本文将继续上一篇博客爬楼梯之后继续讲解同样用到了动态规划的 01背包问题 在解决动态规划问题时,我们经常面临着空间复杂度的挑战。01背包问题是一个典型的例子,通常使用二维数组来表示状态转移,但这样会带来额外的空间开销。在本文中,我们将探讨如何通过优化

    2024年04月11日
    浏览(50)
  • 【动态规划】01背包问题(滚动数组 + 手画图解)

            01背包除了可以用形象的二维动态数组表示外,还可以使用空间复杂度更低的一维滚动数组。 目录 文章目录 前言 一、滚动数组的基本理解 二、确定dp及其下标含义 三、确定递推公式 四、确定初始化 五、确定遍历顺序 1.用物品(正序)遍历背包(正序) 实现代码:

    2023年04月08日
    浏览(26)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包