牛客网《剑指offer》专栏刷题练习之掌握动态规划思想_动态规划 牛客网(1)

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

一、连续子数组的最大和

1、题目要求

在这里插入图片描述
在这里插入图片描述

2、个人题解

2.1、解题思路

首先我们要弄清楚题目的含义:什么是连续子数组?

  • 子数组就是小数组里的元素,原数组里必须含义;加上连续,理解起来就是:该数组是原数组里的一串连续的元素或者单个元素。

搞清楚连续子数组后考虑该题的解法:

  1. 既然单个元素也属于连续子数组这个范畴,那么从第二个元素开始,我们对该元素和他与前一个元素的和比较,将二者中的较大值存到辅助数组dp中。
  2. 定义一个max作为最终的结果,并和数组dp中的元素不断对比,较大值将被赋值给max。
  3. 继续遍历,更新继续往dp数组中放入较大值,同时max也不断更新
  4. 遍历结束,max的值就是连续子数组的最大和

图示助理解:
在这里插入图片描述

2.2、代码实现
class Solution {
public:
    int FindGreatestSumOfSubArray(vector<int> array) {
        if(array.size()==1)
            return \*array.begin();
        int dp[array.size()];
        int max=array[0];
        dp[0]=max;
        for(int i=1;i<array.size();i++){
            int temp=dp[i-1]+array[i];
            dp[i] = temp>array[i]? temp:array[i];
            if(dp[i]>max)
                max=dp[i];
        }
        return max;
    }
};

2.3、代码解析
  • 根据题目可知,数组长度是不小于1的,因此在长度为1的时候,直接返回即可
  • 根据数组长度设置辅助数组dp的长度,初始化dp首元素和max的值为数组首元素的值
  • 从第二个元素开始,将子数组和的最大值存入dp数组并更新max的值
  • 遍历结束后,返回max,程序结束,问题解决。

二、连续子数组的最大和(二)

1、题目要求

在这里插入图片描述
在这里插入图片描述

2、个人题解

2.1、解题思路

该题是在连续子数组的和最大的基础上,返回该连续子数组,这里仍然使用动态规划来解题:

我们仍然要通过辅助数组dp来记录连续子数组的最大值,并根据最大值来更新连续子数组的区间,最后将最长区间作为数组下标,将区间范围的元素全部插入到要返回的数组中。


具体做法:

  1. 创建动态规划辅助数组,记录到下标i为止的最大连续子数组和,下标为0的时候,肯定等于原数组下标为0的元素。
  2. 准备左右区间双指针记录每次连续子数组的首尾,再准备两个双指针记录最大和且区间最长的连续子数组的首尾。
  3. 遍历数组,对于每个元素用上述状态转移公式记录其dp值,更新区间首尾(如果需要)。
  4. 出现一个最大值。且区间长度更大的时候,更新记录最长区间的双指针。
  5. 根据记录的最长子数组的位置取数组。
2.2、代码实现
class Solution {
public:
    /\*\*
 \* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 \*
 \* 
 \* @param array int整型vector 
 \* @return int整型vector
 \*/
    vector<int> FindGreatestSumOfSubArray(vector<int>& array) {
        // write code here
        if(array.size()==1)
            return array;
        vector<int>res;
        vector<int> dp(array.size(),0);
        dp[0]=array[0];
        int ans=dp[0];
        //滑动区间
        int left=0,right=0;
        //最终的区间范围
        int resl=0,resr=0;
        for(int i=1;i<array.size();i++){
            right++;
            //状态转移:连续子数组的最大值
            dp[i]=max(dp[i-1]+array[i], array[i]);
            //区间新起点
            if(dp[i-1]+array[i]<array[i])
                left=right;
            //更新最大值
            if(dp[i]>= ans)
            {
                ans=dp[i];


![img](https://img-blog.csdnimg.cn/img_convert/2e3f7349209995889ec5dab14c6ffb20.png)
![img](https://img-blog.csdnimg.cn/img_convert/15e1fbc58f80b9fd69e13259e4862288.png)

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)**


**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

s://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)**


**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值