LeetCode 53. Maximum Subarray(dynamic programming)

本文探讨了LeetCode上经典的最大子数组和问题,提供了三种不同的解决方案:动态规划的迭代方法、分治策略以及在线算法。通过具体实现代码,帮助读者理解每种方法的核心思想及其时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:https://leetcode.com/problems/maximum-subarray/

题目描述:

Find the contiguous subarray within an array (containing at least one number) which has the largest sum.

For example, given the array [-2,1,-3,4,-1,2,1,-5,4],
the contiguous subarray [4,-1,2,1] has the largest sum = 6.

click to show more practice.

More practice:

If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.

思路一:动态规划,分别求以每个元素结尾的最大和子串,sum[i]为以nums中第i个数字结尾的最大和子串, sums[i]=max{sums[i-1]+nums[i],nums[i]}, 也就是说如果sums[i-1]<0,则起副作用,以nums[i]结尾的最大子串就是单个元素。

代码:

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        vector<int> sum;
        sum.push_back(nums[0]);
        int re=sum[0];
        for(int i=1;i<nums.size();i++)
        {
            sum.push_back(sum[i-1]+nums[i]>nums[i]?sum[i-1]+nums[i]:nums[i]);
            if(sum[i]>re)
                re=sum[i];
        }
        return re;
    }
};
参考链接:动态规划 http://www.cnblogs.com/steven_oyj/archive/2010/05/22/1741374.html

(第二次遇到补充:)思路二:还是动态规划的思路,但是从另一个方面考虑,最大子序列和可能出现在三处地方:或者整个出现在输入数据的左半部,或者整个出现在右半部,或者跨越输入数据的中部而占据左右两半部分。前两种情况可以用递归求解。第三种情况的最大和可以通过求前半部分的最大和(包含前半部分的最后一个元素)以及后半部分的最大和(包含后半部分的第一个元素)而得到,然后将这两个部分加在一起。

此种方法比较复杂,时间复杂度:O(NlogN)

代码:

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int maxVal=0;
        DC(nums,0,nums.size()-1,maxVal);
        return maxVal;
    }
   void DC(vector<int>& nums, int start, int end,int& maxVal)
   {
	if (start >=end)
	{
	    if (start==end)
	        maxVal=nums[start];
	    return;
	}
	int left =0,right=0;
	DC(nums, start, (start+end) / 2,left);
	DC(nums, (start+end)/ 2 + 1, end,right);
	maxVal = max(left, right);
	int thissum = 0;
	int midleft = nums[(start+end) / 2];
	for (int i = (start+end) / 2; i >=start; i--)
	{
		thissum += nums[i];
		if (thissum > midleft)
			midleft = thissum;
	}
	
	thissum = 0;
	int midright = nums[(start+end) / 2 + 1];
	for (int i = (start+end) / 2 + 1; i <=end; i++)
	{
		thissum += nums[i];
		if (thissum > midright)
			midright = thissum;
	}
	int mid = midleft + midright;
	maxVal = max(maxVal, mid);
	return;
   }
};

思路三:觉得本质上和思路一其实是一样的,就是角度不同,并且不用开辟额外的空间存储。所以思路三的算法是联机算法,仅需常量空间并以线性时间运行的练级算法几乎是完美算法。

代码:

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int result=nums[0];//之所以不初始化为0,是因为序列可能出现全负的情况
        int tmpsum=0;
        for(int i=0;i<nums.size();i++)
        {
            tmpsum+=nums[i];
            if(tmpsum>result)
                result=tmpsum;
            if(tmpsum<0)
                tmpsum=0;
        }
        return result;
    }
};



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值