力扣算法题中使用“动态规划”刷题的简单解析:小白向(有实题和答案)

写这篇文章的目的
最近刚刷力扣,就直奔算法题去的,没法做难的,简单的题都够呛,经常看题解才能磕磕碰碰写出来!所以针对算法打算写一些文章记录自己学习的过程。
先来了解一下动态规划的概念
动态规划实际上是一类题目的总称,并不是指某个固定的算法。动态规划的意义就是通过采用递推(或者分而治之)的策略,通过解决大问题的子问题从而解决整体的做法。

动态规划的核心思想是巧妙的将问题拆分成多个子问题,通过计算子问题而得到整体问题的解。而子问题又可以拆分成更多的子问题,从而用类似递推迭代的方法解决要求的问题。

设计状态思路:把不确定的因素确定下来,进而把子问题定义清楚,把子问题定义得简单。动态规划的思想通过解决了一个一个简单的问题,进而把简单的问题的解组成了复杂的问题的解。

下面是力扣原题:

力扣算法题:难度:简单

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

子数组 是数组中的一个连续部分。

 
示例 1:

输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6

看了题目一上来抓破脑皮就一个解题思路,把每一个位置能取到的最大值全给算出来!
要是真让自己实现下来这不得麻烦死。

当时没有这个算法的概念,看了动态规划的解析后,理解了一下:(以下为个人理解,如有不正确的地方请指正!)

1.将问题拆分为多个子问题,子问题还可以被拆分为可重复使用的问题。所以针对此问题可以被拆分为。

子问题 1:以 -2 结尾的连续子数组的最大和是多少;
子问题 2:以 1 结尾的连续子数组的最大和是多少;
子问题 3:以 −3 结尾的连续子数组的最大和是多少;
子问题 4:以 4 结尾的连续子数组的最大和是多少;
子问题 5:以 −1 结尾的连续子数组的最大和是多少;
子问题 6:以 2 结尾的连续子数组的最大和是多少;
子问题 7:以 1 结尾的连续子数组的最大和是多少;
子问题 8:以 −5 结尾的连续子数组的最大和是多少;
子问题 9:以 4 结尾的连续子数组的最大和是多少。

这样做的好处是每个子问题都只要找到自己最大的和,然后下一个子问题重复利用上一个子问题的结果进行对比,直到找出最大的和。

2.那么根据这个顺序来,我们从-2开始
假设指针为k,
那么k等于0时,这个nums[k]则最大值为0.
k等于1时,nums[k]最大值为1,
k等于2时,nums[k]最大值为1。
这是从你主观意识计算判断出来的结果,写进程序是不可能的。

我们将每个子问题的和留给下一个子问题使用,所以设max为最大值。
k等于0时,数组只有1种情况{-2} 所以max = -2.
k等于1时,数组有3种情况{-2}、{-2,1}、{1},所以max = 1。
分析这种情况,{-2}是上一个子问题的结果。所以上一个问题的最大值已经知道了,我们只需要比对{1}和{-2,1}这两种情况,然后将这两个数组的总和大的那个值再和max存的值进行对比。这样我们就将当前这个子问题的最大值求出来了。
由此,
当k等于2时,数组有种,{-2}、{-2,1}、{1},以及{-3}、{-2,1,-3}、{1,-3},6种情况。
分析这种情况,其中{-2}、{-2,1}、{1}中的最大值已经在上一个子问题求得最大值为1,所以不用比对此部分,直接存储在max中。

所以在这只分析{-2,1,-3}、{1,-3}、{-3}
这里比较重要,我们在上一个子问题[-2,1]中可以求得{-2,1}和{1}哪一个值大,此处为什么不算上{-2}这个情况,因为这个情况已经在k=0时已经求得,但是k=0时没有可对比的,所以我没做逻辑解析。根据这就相当于我们已经比对了{-2,1,-3}、{1,-3}这两个数组的总和谁大!所以我设{-2,1}和{1}对比值更大的那个数组为pre,这样就只用比对{pre,-3}和{-3}这两个情况了(写到这我自己才大悟ahhhh,记下来是个不错的选择)。比对{pre,-3}和{-3}之后谁大就将谁存入pre,因为要准备给下一个问题使用,再用已有的max和pre进行比对,谁大就存入max。
**所以k = 3时你会了吗?**不理解可以讨论一下。不一定我说的就完全对,但是我觉得逻辑是没错的!

下面是看了解析后自己的解法

class Solution {
    public int maxSubArray(int[] nums) {
        int length = nums.length;
        int pre = nums[0]; //上一个nums[i]中的最外面两个数组分别求和比对的最大值例如i= 2时{1,-3}和{3}比对的最大值
        int max = pre;
        if(length == 1){
            return pre; 
        }
        for(int i = 1; i < length; i++){//i = 1的原因需要解释吗?就当我提醒别忘了是从1开始的哦!
            pre = Math.max(pre + nums[i],nums[i]);
            max = Math.max(pre,max);
        }
        return max;   
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值