C++解OJ题--最大子数组和(第一次尝试动态规划,很烧脑)

  虽然这道题标注的是简单,但是对于我一个新手来说还真的挺烧脑的。


我想说:
  对于动态规划的知识,我可谓花了大功夫。各种看视频看博客折腾了一整天,不夸张真的是一整天。你以为我懂了,不,这种东西我看下来更本不可能短时间掌握。那在这一整天中我的收获是什么?收获了动态规划的思想及解题步骤。

思想:利用已知的历史记录来完成对未知记录的计算,从而避免重复的计算。
  通俗的讲就是我们要将已经计算过的记录进行备份,下次碰见直接拿来用,而不用重新去计算一遍。
  那用什么来进行备份?对就是变量,或者是一维数组,或者是二维数组。

解题步骤:
  通过走访各大成功人士,总结出动态规划按照如下的几步来完成。
1.定义dp数组所表示的含义
  解动态规划题的时候我们都会开辟一个数组,叫dp(Dynamic Programming)数组,可能是一维数组,也有可能是二维数组。我们要明确数组下标所代表的含义及数组元素所代表的意思

2.确定递推公式
  通俗的讲就是确定数组元素间的关系式。这一步很核心,也很难。通常我会从这两个方面来确定:最后一步、子问题。
最后一步:假设前面的若干步已经是全局最优的,那最后一步如何选择也是全局最优。
子问题:将大问题分解成若干的小问题来进行考虑

3.确定初始条件及边界情况
  dp数组中一些不能进行分解计算的要直观的给出结果。而边界情况一般就指数组不能越界

4.遍历顺序(计算顺序)
  按照怎样的顺序去计算(小->大;大->小)
计算顺序的确定只有一个原则:当要算递推公式等式左边的时候,等式右边用到的状态都已经算过了

  光说不练哪还是不行的,下面的这道OJ题我会严格按照如上的解题思想及步骤来完成


原题如下:

C++解OJ题--最大子数组和(第一次尝试动态规划,很烧脑)_第1张图片
  给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
  子数组 是数组中的一个连续部分。

题意:
  就是计算一个已知数组的最大连续子序列和。返回这个最大值


按步骤进行:
1.定义dp数组所表示的含义。
  我们的问题是求解一个数组中的最大连续子序列和。那我们就定义dp[i]的含义是:nums数组中前 i +1 个数据所组成的数组的最大子序和为dp[i]
2.确定递推公式。
  假设我们要求解 i 个数据的最大子序列和,现在我们已经知道了 i-1 个数据的最大子序列和为dp[i-1]。那么当将最后一个数据加入后,dp[i]的值取决于什么呢?dp[i]的值取决于 dp[i-1] +nums[i] 与nums[i] 中的较大者。所以递推公式为:dp[i]=max(dp[i-1]+nums[i],nums[i]

3.确定初始条件及边界
  哪些情况我们是不能用递推公式分解来计算的。当 i =0时,由于数组下标无负数,所以dp[0]我们要直观的给出。即初始化:dp[0]=nums[0],边界情况为数组不能越界,也就是dp数组的大小为给定数组的大小。

3.计算顺序
  根据递推公式等式左边的要等与等式右边的,而i > i -1,则说明要从小到大进行遍历。

示意图如下:
C++解OJ题--最大子数组和(第一次尝试动态规划,很烧脑)_第2张图片
C++解OJ题--最大子数组和(第一次尝试动态规划,很烧脑)_第3张图片


代码实现:

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int numsSize=nums.size();//数组大小,为nums数组的大小
        vector<int>dp(numsSize);//开辟dp数组
        dp[0]=nums[0];//不能分解的情况
        int Max=dp[0];//用于标记最大子序列和
        for(int i=1;i<numsSize;i++)
        {
            dp[i]=max(dp[i-1]+nums[i],nums[i]);
            Max=max(dp[i],Max);
        }
        return Max;//返回最大子序列和
    }
};

  按照上面的思路步骤确实是可行的,当然以后的时间我也会用实践来证明。


  我是老胡,感谢阅读!!❤️ ❤️

你可能感兴趣的:(OJ题--动态规划,动态规划,c++,算法,数据结构,leetcode)