题目描述:

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.

题目要求找出最大的连续子序列的和, 首先采用一种分治法. 对于一个数组, 把它中中间分成两半, 和最大的连续子序列可能出现在左半边, 可能出现在右半边, 也有可能出现跨越左右的情况. 对于在左半边或右半边的情况, 可以使用递归缩小问题, 对于跨越左右的情况, 可以使用线性算法来获得结果. 最后返回三个值中的最大值.

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        return maxSub(nums, 0, nums.size());
    }

    int maxSub(vector<int>& nums, int left, int right) {
        if (right - left == 1) {
            return nums[left];
        }
        int leftSum, rightSum, mid = (left + right) / 2;
        leftSum = maxSub(nums, left, mid);
        rightSum = maxSub(nums, mid, right);

        int midLeftSum = 0, midLeftMaxSum = INT_MIN, midRightSum = 0, midRightMaxSum = INT_MIN;
        for (int i = mid - 1; i >= left; i--) {
            midLeftSum += nums[i];
            if (midLeftSum > midLeftMaxSum) midLeftMaxSum = midLeftSum;
        }
        for (int i = mid; i < right; i++) {
            midRightSum += nums[i];
            if (midRightSum > midRightMaxSum) midRightMaxSum = midRightSum;
        }
        int midSum = midRightMaxSum + midLeftMaxSum;

        return max(midSum, max(leftSum, rightSum));
    }
};

还可以使用动态规划法. 使用dp[i]来表示包含nums[i]的和最大的连续子串的和. 如果dp[i-1]是大于0的, 那么就可以加上dp[i-1], 因为nums[i]是必须有的. 用另一种方式来说, 这个题目的主要问题在于和最大的连续子串中可能出现负数, 要考虑的是负数及负数之前的子串要不要加到当前子串中来, 而这个判断就是看以该负数结尾的连续子串的和是否大于0, 如果小于0则不能加进来, 大于0则可以.

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        vector<int> dp(nums.size(), 0);
        int ret = nums[0];
        dp[0] = nums[0];
        for(int i = 1; i < nums.size(); i++){
            dp[i] = dp[i - 1] > 0 ? dp[i - 1] + nums[i] : nums[i];
            if(ret < dp[i])
                ret = dp[i];
        }
        return ret;
    }
};