首页 > 其他分享 >喜欢dp动态规划的第二天(暑假提升)

喜欢dp动态规划的第二天(暑假提升)

时间:2024-07-16 17:56:44浏览次数:9  
标签:hash int 这题 暑假 题目 动态 dp 回文

不要失去信心,只要坚持不懈,就终会有成果。——钱学森


dp动态规划题目详解--第二天

前言

由于上一期的动态规划我觉的太过于繁琐,所以这次简化一下操作,题目概念解析将不会再写,我直接写题目的意思和直接引导出做法,当然,其中我觉得很重要的地方会讲的深入一点,希望读者能够好好的理解。

1、 最长定差子序列

题目链接在这
题目解答: 这里的第一道题目相当于是抛砖引玉的作用,后面的几道题目就能感受到具体的作用了。
寻找最长的定差子序列。我知道,在上一篇文章已经讲过一遍了,但是当时没有多大的抛砖引玉的作用,这里作为第一题还是希望能够对下面集体能够有反思,并且能够理解优化和处理一些两个末尾位置有限制时候的操作。
详细过程参考

2、 最长等差数列

题目链接在这
题目解答: 一开始,我觉的这题和最长斐波那契的那道题目很相似,但是这题肯定有不一样的地方,就比如说斐波那契数是固定的递增的数组,还有一种可能就是说这个还可能是重复的,那重复的话还要找到离最后两个以及确定下的数的位置最近的一个数,因为找最近的情况下,才可能是得到最长的等差数列。除此之外,这题的没有顺序导致的会是有关下表问题的出现。所以说这里就不能够完全利用那道题目的方法来解决,所以需要考虑另外的方法,那应该怎么弄呢?由于斐波那契那道题目是递增的,所以说递增的条件之下,那道题目是不会有这道题的在意的地方,所以说这题才需要另外的考虑。
解题代码:

class Solution {
public:
    int longestArithSeqLength(vector<int>& nums) 
    {
        unordered_map<int,int>hash;
        int ret=2;
        int n=nums.size();
        //hash[nums[0]]=0;
        for(int i=0;i<n;i++)hash[nums[i]]=i;
        vector<vector<int>>dp(n,vector<int>(n,2));
        for(int i=1;i<n;i++)
        {
            for(int j=i+1;j<n;j++)
            {
                int a=2*nums[i]-nums[j];
                if(hash.count(a))
                dp[i][j]=dp[hash[a]][i]+1;
                ret=max(ret,dp[i][j]);
            }
            //hash[nums[i]]=i;
        }
        return ret;
    }
};

其中为了解决下表问题,我们更新二维dp表的时候是固定i的位置,让j从i+1开始,向后移动,这样的好处是能够处理的更加的“丝滑”。怎么个事呢?由于i的位置是不动的,所以说hash表的更新是较少的,较少是因为只有在i变化的时候hash才需要再次更新。这样的话既能够消除数组中存在多个相同数的影响,并且也能够实现找到最近的数的位置,两全其美,优化了复杂程度还能解决问题。

3、等差数列划分 II - 子序列

题目链接在这
题目解答: 很疑惑啊,很疑惑,一开始,我在想这题和上一个的最长等差数组有什么区别吗,只不过是变成了找个数而已啊!其实不然,对于这道题来说,这题的优化和上面两个的又不一样,上面的第二题是把倒数第三个目标数的存储是实时更新的,但是对于这题来说这里需要保存每一个数的位置,因为是等差的个数,而且不是最长的等差的个数。所以保存位置最适合之前处理不同的地方,很重要。

解题代码:

class Solution {
public:
    int numberOfArithmeticSlices(vector<int>& nums) 
    {
        unordered_map<long long,vector<int>>hash;
        int n=nums.size();
        for(int i=0;i<n;i++)
        {
            hash[nums[i]].push_back(i);
        }
        vector<vector<int>>dp(n,vector<int>(n));
        int ret=0;
        for(int j=2;j<n;j++)
        {
            for(int i=1;i<j;i++)
            {
                long long a=(long long)nums[i]*2-nums[j];
                if(hash.count(a))
                {
                    for(auto k:hash[a])
                    {
                        if(k<i)dp[i][j]+=dp[k][i]+1;
                        else
                        break;
                    }
                }
                ret+=dp[i][j];
            }
        }
        return ret;
    }
};

4、回文子串

题目链接在这
题目解答:
三种普遍的算法解决回文子串问题。
其中的时间复杂度和空间复杂度都是基于本题来说

算法种类时间复杂度空间复杂度
中心扩展算法O(N2)O(1)
马拉车算法O(N)O(N)
动态规划O(N2)O(N2)

其中,动态规划的思路是值得学习的,有时候还能将hard的题目直接变为easy的题目。
利用二维dp表,dp[i][j]表示起始位置为i,结束为止为j的字符串是否为回文子串。所以在循环的时候只需要循环dp表的上三角部分,就能够实现回文串个数的判断。
又由于特殊的时候就比如i= =j或i= =j-1的时候是需要特殊判定的,并且判定之后呢,会消除对于dp表中越界访问的情况。
由dp表的转移状态方程能够得到关键是,从左下角的二维数组的位置向上更新,所以在填表的顺序的时候就必须要使用从下向上的方法来实现。

解题代码:
中心扩展算法:

class Solution {
public:
    int countSubstrings(string s) 
    {
        int n=s.size();
        int ret=0;
        int left=0,right=0;
        while(right<n)
        {
            int lefttmp=left,righttmp=right;
            while(lefttmp>=0&&righttmp<n&&s[lefttmp--]==s[righttmp++])
            ret++;
            lefttmp=left-1,righttmp=right;
            while(lefttmp>=0&&righttmp<n&&s[lefttmp--]==s[righttmp++])
            ret++;
            right++;
            left++;
        }
        return ret;
    }
};

其中的要点就是关于right当时所处在的位置的字符是作为偶数个数回文串的中心部位,还是奇数个数回文串的正中间的部分。这就是重点地方。
动态规划:

class Solution {
public:
    int countSubstrings(string s) 
    {
        int n=s.size();
        vector<vector<bool>>dp(n,vector<bool>(n));
        int ret=0;
        for(int i=n-1;i>=0;i--)
        {
            for(int j=i;j<n;j++)
            {
                if(s[i]==s[j])
                    dp[i][j]=i+1<j?dp[i+1][j-1]:true;
                if(dp[i][j]==true)ret++;
            }
        }
        return ret;
    }
};

5、总结

虽然题目不多,但是其中相对于上一篇文章中的利用dp解决问题的方法有稍微的提升,从一维逐渐向使用二维,从dp表的直接使用到利用hash优化程序。并且从原来的最后一位能够推出前面全部的定差数组,也变成了需要两个末了位置的数才能推导出前面的所有数的转变。同时方法也会改变,一些hash表的更新也同时尤为重要,究竟是一边跟随着循环的更新,还是在循环开始之前先遍历一遍都显得尤为重要,究竟是不断改变hash出现过数的下表还是存起来方便以后的问题的解决。
这些都是从这四道题目中选取出的知识点,有关于dp表使用方法的知识点。

标签:hash,int,这题,暑假,题目,动态,dp,回文
From: https://blog.csdn.net/2301_79194984/article/details/140443049

相关文章

  • AT_dp_a Frog 1 题解
    Frog1题面翻译NNN个石头,编号为1,2......
  • dm/dp含义和接线
    dm/dp含义和接线DM:dataminus,DM是USB的数据线D-(白色线)DP:dataplusDP是USB的数据线D+(绿色线)usb接线排列方式是VCC,D-,D+,GNDDigitalPositive&DigitalMinusUSB的通信都是由主机发起的(iic类似)USB使用差分传输模式,有两条数据线,分别是:a.USB数据......
  • 随手记:Bruno动态注入Header
    因为PostMan启动太慢,动不动就要登录,以及防火墙的问题,搞起来挺麻烦,一气之下就换了Bruno来管理API请求,接口的安全校验也是很正常的事儿,最近有个兄弟部门使用了参数+时间戳+HmacSHA256校验,把校验的Sign放到Header里,研究了下,做个记录,方便随取随用,这种动态的Header需要使用Script:cons......
  • winform 动态截断或者补全文字宽度
    使用TabControl时,发现它的选项卡宽度会随文字长度变化,我自己做了一个浏览器,发现很难看,于是写了上算法,对文字长度进行填充或截断,效果很不错: 调用代码:using(varg=tabs.CreateGraphics()){tabPage.Text=""+PadAndEllipsis(g,tabs.Font,title,150)+""......
  • 【DG】DataGuard动态性能视图及日志传输/应用服务说明
    一、DataGuard相关动态性能视图 序号 动态性能视图名称 说明1 v$database 查询打开模式,角色,保护模式,保护级别2 v$managed_standby 备库查询进程情况,RFS、MRP03 v$standby_log 查看standbyredolog4 v$archive_dest_statu......
  • 聊聊springboot项目脱离配置中心,如何实现属性动态刷新
    前言如果大家有开发过微服务项目,那对配置中心应该是耳熟能详了,配置中心有个很有用的能力,就是热更新属性,即不重启服务,就能做到属性的动态变更。而我们今天讲的话题是,怎么样不使用配置中心,也能达到如上的效果如何实现属性的热更新如果我们属性是配置在配置文件中,我们可以通过监听......
  • UDP网络编程java实现
    UdpUdp服务端实现步骤:创建Udp对象,监听端口创建数据包(数据包,数据长度)接收数据包(数据包)读取数据包,并输出将字节数组转化为字符串响应客户端消息(设置数据包)发送数据包//监听端口号DatagramSocketdatagramSocket=newDatagramSocket(6666);//创建数据包byte[]buff......
  • 矩阵优化 DP 以及全局平衡二叉树实现的动态 DP 学习笔记
    矩阵乘法求斐波那契数列的第\(n\)项,其中\(n\le10^{18}\),对数\(m\)取模。写出转移方程,\(f_i=f_{i-1}+f_{i-2}\),直接算是\(O(n)\)的,似乎没什么办法优化。定义大小分别为\(n\timesp\)和\(p\timesm\)的矩阵(分别为\(a\)和\(b\))相乘的结果(矩阵\(c\))是一个大小为\(......
  • 状压DP
    状压DP状压DP是动态规划的一种,通过将状态压缩为整数来达到优化转移的目的。例题https://www.luogu.com.cn/problem/P1896思路一行中所有放置的状态可以用二进制数表示:如01000111(1代表当前位置放置物品)因此,我们可以先找出所有的合法状态,(利用dfs进行递归)并用sit[i]记录第......
  • lamp基本架构+wordpress
    一、安装并设置MariaDB1、时钟同步先安装chrony,重启并设置enable,最后同步yum-yinstallchrony2、安装mariadb和httpdyum-yinstallhttpdmariadbmariadb-server将httpd和mariadb重新启动并enable3、设置mariadb数据库进入数据库进行初始化mysql_secure_......