剑指offer42:连续子数组的最大和

方法一:动态规划

我们看到这道题,第一眼是不是很想用暴力去做嘿嘿,就是来个两层循环,然后对每个区间都求一次和,返回其中最大的。。。但是这个时间复杂度是O(n^2),题中要求的是O(n),只能说可惜~

那我们来一次分析啥的,这里cvOffer中的东西,具体可以看offer中的P218:

[1,-2,3,10,-4,7,2,-5]

从头到尾分析数组的规律:初始化和为0,第一步加上1,此时和为1,第二步加上-2,和变成-1,第三步加上三,由于前面的和为-1,小于0,如果还要求和,那么比3还会小,所以,我们直接抛弃前两个的-1,从3开始继续求和,emmm,是不是有点感觉了?

没错,规律就是这样,这可以用动态规划的转移方程来清晰地刻画,设f(i)表示以第i个元素结尾的最大连续和,输入的是nums:

f(i)=\left\{\begin{matrix} nums[i], i=0orf(i-1)\leqslant 0\\ nums[i]+f(i-1), i\neq 0andf(i-1)>0 \end{matrix}\right.

这样我们就可以自底向上写一个小小的动态规划出来:

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int len=nums.size();
        vector<int> ans(len);
        int max=INT_MIN;
        for(int i=0;i<len;++i)
        {
            if(i==0 || (i>0&&ans[i-1]<=0))
            {
                ans[i]=nums[i];
            }
            else
            {
                ans[i]=nums[i]+ans[i-1];
            }
            if(ans[i]>max)
            {
                max=ans[i];
            }
        }
        return max;
    }
};

结果是这样:

 emmm看到这个结果,时间复杂度上面确实满足要求了,但是这个空间复杂度是否有点??。。

所以有什么好一点的方法来解决这个问题呢?我们可以用滚动数组,这名字看起来好像很神奇,其实我至今都无法理解为什么叫滚动数组......whatever,我的理解就是,在动态规划的求某个f(i)的过程中,其实我们只用到了当前的nums[i]和一个f(i-1)所以我们没必要开个数组,只需要用一个变量记录之前的f(i-1)就行了,具体实现代码如下:

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int len=nums.size();
        int pre=nums[0],now;
        int max=INT_MIN;
        for(int i=0;i<len;++i)
        {
            if(i==0 || (i>0&&pre<=0))
            {
                now=nums[i];
            }
            else
            {
                now=nums[i]+pre;
            }
            if(now>max)
            {
                max=now;
            }
            pre=now;
        }
        return max;
    }
};

结果如下所示:

嘿嘿,只能说萨巴拉稀

翻过去看看官方的写法,是这样的:

第一种也是动态规划:

 代码如下:

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int pre = 0, maxAns = nums[0];
        for (const auto &x: nums) {
            pre = max(pre + x, x);
            maxAns = max(maxAns, pre);
        }
        return maxAns;
    }
};

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/lian-xu-zi-shu-zu-de-zui-da-he-lcof/solution/lian-xu-zi-shu-zu-de-zui-da-he-by-leetco-tiui/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

能把这个东西写成递归,确实没想过。。。

以上动态规划的时间复杂度均为O(n)

方法二:分治法

看答案看着看着发现还有个分治法,这是什么神奇的东西。。。来看一看,和线段树有关啊,那没事了,先挂在这,以后写了线段树再回来看看吧。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值