LeetCode 53. 最大子序和(贪心+动态规划+分治)

54 篇文章 0 订阅

1.题目

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

示例:

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

如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximum-subarray
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2.题解

贪心

先将数组第一个元素存到返回值中,防止只有一个元素并且为负数时错误;
思路是:维护sum变量,记录前几项的和,每次更新res记录最大和,若为sum正数继续加,若为负数,则应该将sum变量置为使得sum为负数的下一个元素值。最终返回res。

class Solution
{
public:
    int maxSubArray(vector<int>& nums)
    {
        int res = nums[0], sum = 0;
        for(int num : nums)
        {
            if(sum >= 0) sum += num;
            else sum = num;
            res = max(res, sum);
        }
        return res;
    }
};

动态规划

再一次遍历中,更新以第i位结尾时,用一个数组记录子序列和的最大值,之后线性查找最大值即可。
空间优化,数组可以用一个在循环外面的变量记录以当前项结尾的最大值。

class Solution
{
public:
    int maxSubArray(vector<int>& nums)
    {
        int res = nums[0], sum = 0;         //res记录结果,sum记录当前以i结尾的最大和
        for(int num : nums)
        {
            sum = max(num, sum + num);      //比较第i项 和第i项加前i-1项的和中的较大者
            res = max(res, sum);            //记录前i项中最大的子序列和
        }
        return res;
    }
};

分治

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

class Solution
{
public:
    struct Status
    {
        int lSum, rSum, mSum, iSum;
    };

    Status pushUp(Status l, Status r)
    {
        int iSum = l.iSum + r.iSum;
        int lSum = max(l.lSum, l.iSum + r.lSum);
        int rSum = max(r.rSum, r.iSum + l.rSum);
        int mSum = max(max(l.mSum, r.mSum), l.rSum + r.lSum);
        return (Status)
        {
            lSum, rSum, mSum, iSum
        };
    };

    Status get(vector<int> &a, int l, int r)
    {
        if (l == r) return (Status)
        {
            a[l], a[l], a[l], a[l]
        };
        int m = (l + r) >> 1;
        Status lSub = get(a, l, m);
        Status rSub = get(a, m + 1, r);
        return pushUp(lSub, rSub);
    }

    int maxSubArray(vector<int>& nums)
    {
        return get(nums, 0, nums.size() - 1).mSum;
    }
};

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值