六、[LeetCode OJ]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.

问题来源:Maximum Subarray

【问题分析】

题意:先来理解一下题意,给定一个数组,找出一个连续的子数组,使得子数组之和是最大值。

方法一:令max = nums[0],sum = 0。遍历nums,nums[i]与sum相加,如果sum大于max,用sum替换max的值;如果sum小于0了,重置sum为0,最后返回max,时间复杂度为遍历一遍数组O(N )。

方法二:分治方法:
我们首先定义几个参数:
sum——一个数组的和;
leftmx——从数组最左开始最大的和;
rightmx——从数组最右开始最大的和;
mx——数组最大的和。
将一个数组A从中间分开,变成两个子数组A1和A2,leftmx1,rightmx1,mx1,sum1表示子数组A1的参数,leftmx2,rightmx2,mx2,sum2表示子数组A2的参数。
有以下关系:
mx = max(max(mx1, mx2), rightmx1 + leftmx2);
leftmx = max(leftmx1, sum1 + leftmx2);
rightmx = max(rightmx2, sum2 + rightmx1);
sum = sum1 + sum2。
对子数组也进行上面的分治操作,直到数组变成不可拆分的单元,即left等于right,此时leftmx = rightmx = mx = sum = nums[left]。
最后返回mx。T(n) = 2T(n/2) + O(1),时间复杂度为O(N)。


【源代码】

方法一:
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int max = nums[0];
        int sum = 0;
        int i = 0;
        while (i < nums.size()) {
        	sum += nums[i];
        	if (sum > max) {
        		max = sum;
        	}
        	if (sum < 0) {
        		sum = 0;
        	}
        	i++;
        }
        return max;
    }
};

方法二(分治方法):
/**
sum-------the total sum of the subarray.
leftmx----largest sum starting from the left most element.
rightmx---largest sum starting ending the right most element.
mx--------largest sum of the subarray.
**/
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        if (nums.size() == 0) {
        	return 0;
        }
        if (nums.size() == 1) {
            return nums[0];
        }
        int mx,leftmx,rightmx,sum = 0;
        maxSubArray(nums, 0, nums.size()-1, mx, leftmx, rightmx, sum);
        return mx;
    }
private:
	void maxSubArray(vector<int>& nums, int left, int right, int& mx, int& leftmx, int& rightmx, int& sum) {
		if (left == right) {
			mx = leftmx = rightmx = sum = nums[left];
		} else {
			int leftmx1, sum1, rightmx1, mx1 = 0;
			int leftmx2, sum2, rightmx2, mx2 = 0;
			int mid = (left + right) / 2;
			maxSubArray(nums, left, mid, mx1, leftmx1, rightmx1, sum1);
			maxSubArray(nums, mid+1, right, mx2, leftmx2, rightmx2, sum2);
			mx = max(max(mx1, mx2), rightmx1 + leftmx2);
			leftmx = max(leftmx1, sum1 + leftmx2);
			rightmx = max(rightmx2, sum2 + rightmx1);
			sum = sum1 + sum2;
		}
	}
};




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值