Leetcode53——最大子数组和(一题多解)

一、题目

https://leetcode.cn/problems/maximum-subarray/submissions/568155647/

二、思路&代码

V1.0:

一般看到连续子序列或子数组优先考虑的都是前缀和数组,但是在本题中我们可以采用两个变量来判断。①cursum,用来记录连续子数组截止到目前的和,②maxres,用来记录连续子数组的最大和。关键点:当cursum<0时,我们就把cursum置为0,从头开始计算,因为一旦前面那一串小于0了,后面的再加上前面那一串势必是减小的,所以不可能成为最大连续子数组,故我们从头开始构造,代码如下:

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int len=nums.size();
        int cursum=0;
        int maxres=0;
        //如果<0,则说明加上前面那一串肯定不会更大
        for(int i=0;i<len;i++)
        {
            cursum+=nums[i];
            maxres=max(maxres,cursum);
            if(cursum<0) cursum=0;
        }
        return maxres;
    }
};

但是这个版本在提交的时候部分点wa了,经过观察发现这个版本没有考虑到最大子数组和始终是负数的情况,这种情况下上述代码仍然返回0,显然是不对的,所以我们进行下面改进:

V2.0:

class Solution {
public:
    //1.0:没有考虑到全是负数的情况,或者任一子数组和都是负数的情况
    int maxSubArray(vector<int>& nums) {
        int len=nums.size();
        int cursum=0;
        int maxres=0;
        //如果<0,则说明加上前面那一串肯定不会更大
        for(int i=0;i<len;i++)
        {
            cursum+=nums[i];
            //以免0永远为最小值
            if(i>0) maxres=max(maxres,cursum);
            else maxres=cursum;
            //cursum+=nums[i];
            if(cursum<0) cursum=0;
        }
        return maxres;
    }
};

在这段代码中,我们新增了一个判断条件,即在开始的初始化时,我们让maxres的值直接等于第一个元素的值,而不是0,这样就能保证以免0永远是最小值的问题,实际上,可以直接简化为下面版本,代码如下:

V3.0:

class Solution {
public:
    //1.0:没有考虑到全是负数的情况,或者任一子数组和都是负数的情况
    int maxSubArray(vector<int>& nums) {
        int len=nums.size();
        int cursum=0;
        int maxres=nums[0];
        //如果<0,则说明加上前面那一串肯定不会更大
        for(int i=0;i<len;i++)
        {
            cursum+=nums[i];
            maxres=max(maxres,cursum);
            if(cursum<0) cursum=0;
        }
        return maxres;
    }
};

V4.0:

以上算法的时间复杂度均为O(n),本题还可以考虑用分治法来做,即它的最大子数组和要么在左半边,要么在右半边,要么是穿过中间,对于左右边的序列,情况也是一样的。分别计算后返回左、右、中三者的最大值即可,用递归不断将大问题化解成小问题,然后分解实现。这时的事件复杂度是O(nlogn),可以自行尝试代码,最后也能通过 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值