53. Maximum Subarray

Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.

Example:

Input: [-2,1,-3,4,-1,2,1,-5,4],
Output: 6
Explanation: [4,-1,2,1] has the largest sum = 6.

Follow up:

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

普通解:

分析:这是一道优化题,大多数优化类题目都可以用DP解决,所以本题也可以用DP的方法解决。

当我们确定用DP的方法解决时,就需要确定此问题的子问题是什么。此题的子问题可以定为 maxSubArray(vector<int> &nums, int i); 就是在子序列nums[0:i] 中的最大序列。

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

优质解:Divide and Conquer(分治思想)

待学习。。。。。。

1) Divide the given array in two halves
2) Return the maximum of following three
….a) Maximum subarray sum in left half (Make a recursive call)
….b) Maximum subarray sum in right half (Make a recursive call)
….c) Maximum subarray sum such that the subarray crosses the midpoint

The lines 2.a and 2.b are simple recursive calls. How to find maximum subarray sum such that the subarray crosses the midpoint? We can easily find the crossing sum in linear time. The idea is simple, find the maximum sum starting from mid point and ending at some point on left of mid, then find the maximum sum starting from mid + 1 and ending with sum point on right of mid + 1. Finally, combine the two and return.

 

// A Divide and Conquer based program for maximum subarray sum problem 
#include <stdio.h> 
#include <limits.h> 

// A utility funtion to find maximum of two integers 
int max(int a, int b) { return (a > b)? a : b; } 

// A utility funtion to find maximum of three integers 
int max(int a, int b, int c) { return max(max(a, b), c); } 

// Find the maximum possible sum in arr[] auch that arr[m] is part of it 
int maxCrossingSum(int arr[], int l, int m, int h) 
{ 
    // Include elements on left of mid. 
    int sum = 0; 
    int left_sum = INT_MIN; 
    for (int i = m; i >= l; i--) 
    { 
        sum = sum + arr[i]; 
        if (sum > left_sum) 
        left_sum = sum; 
    } 

    // Include elements on right of mid 
    sum = 0; 
    int right_sum = INT_MIN; 
    for (int i = m+1; i <= h; i++) 
    { 
        sum = sum + arr[i]; 
        if (sum > right_sum) 
        right_sum = sum; 
    } 

    // Return sum of elements on left and right of mid 
    return left_sum + right_sum; 
} 

// Returns sum of maxium sum subarray in aa[l..h] 
int maxSubArraySum(int arr[], int l, int h) 
{ 
// Base Case: Only one element 
if (l == h) 
    return arr[l]; 

// Find middle point 
int m = (l + h)/2; 

/* Return maximum of following three possible cases 
    a) Maximum subarray sum in left half 
    b) Maximum subarray sum in right half 
    c) Maximum subarray sum such that the subarray crosses the midpoint */
return max(maxSubArraySum(arr, l, m), 
            maxSubArraySum(arr, m+1, h), 
            maxCrossingSum(arr, l, m, h)); 
} 

/*Driver program to test maxSubArraySum*/
int main() 
{ 
int arr[] = {2, 3, 4, 5, 7}; 
int n = sizeof(arr)/sizeof(arr[0]); 
int max_sum = maxSubArraySum(arr, 0, n-1); 
printf("Maximum contiguous sum is %dn", max_sum); 
getchar(); 
return 0; 
} 

 

posted @ 2019-11-27 09:44  强威  阅读(203)  评论(0编辑  收藏  举报