【Leetcode刷题】---动态规划--53.最大子序和

题目描述: 最大子序和      
        给定一个序列(至少含有 1 个数),从该序列中寻找一个连续的子序列,使得子序列的和最大。

        例如,给定序列 [-2,1,-3,4,-1,2,1,-5,4],
        连续子序列 [4,-1,2,1] 的和最大,为 6。

扩展练习:

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

解:使用动态规划规划的思想,求一个序列中连续子序列的最大和,定义状态,定义一个数组dp[i],表示以第i个元素为结尾的当前连续子序列的最大和。dp[0]--dp[i-1]表示已经求出的以i-1为结尾的最大子序和。如果dp[i-1]<0,那么dp[i]加上前面长度任意子序和都会小于不加前面的子序和。状态转移方程为:

dp[i]=nums[i]   if dp[i-1]<=0

dp[i]=dp[i-1]+nums[i]   if dp[i-1]>0

 

class Solution {
public:
    int maxSubArray(vector&nums){
	int len=nums.size();
	if(len==0)
		return 0;
	if(len==1)
		return nums[0];
	vector dp(len,0);
	dp[0]=nums[0];
	int maxNum=nums[0];
	for(int i=1;i0)
			dp[i]=dp[i-1]+nums[i];
		else
			dp[i]=nums[i];
		maxNum=max(dp[i],maxNum);
	}
	return maxNum;
}
};

分治法:

思路:假设数组下标有效范围是l到r,将数组分为左半部分下标为(l,mid-1)和右半部分下标为(mid+1,r)以及中间元素下标为mid,接下来递归求出左半部分的最大子序和:left=maxNum(nums,l,mid-1); 右半部分最大子序和right=maxNum(nums,mid+1,r);

接下来再将左半部分右边界,右半部分左边界以及中间元素nums[mid]整合,用了两个循环,先整合左半部分右边界和中间值,再将整合结果与右半部分左边界整合得到整合以后的最大子序和max_num,最后返回max_num,left,right的最大值即是要求的最大子序和。
 

class Solution {
public:
    int maxSubArray(vector&nums)
{
	if(nums.size()==0)
		return 0;
	return maxSum(nums,0,nums.size()-1);
}
int maxSum(vector&nums,int l,int r)
{
	if(l>r)
		return INT_MIN;
	if(l==r)
		return nums[l];
	int mid=(l+r)/2;
	int leftMaxNum=maxSum(nums,l,mid-1);
	int rightMaxNum=maxSum(nums,mid+1,r);
	int maxNum=nums[mid];
	int temp=nums[mid];
	for(int i=mid-1;i>=l;i--){
		temp+=nums[i];
		maxNum=max(maxNum,temp);
	}
	temp=maxNum;
	for(int j=mid+1;j<=r;j++){
		temp+=nums[j];
		maxNum=max(maxNum,temp);
	}
	return max(max(leftMaxNum,rightMaxNum),maxNum);
}
};

 

你可能感兴趣的:(#,Leetcode刷题)