最大子序和

LeetCode第53题

题目描述:
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

示例:

输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximum-subarray

思路

采用分治法来做,时间复杂度会比较低。将数组分为左子数组和右子数组。那么最大子序就有三种存在位置:完全被包含于左子数组,完全被包含于右子数组,跨越中点同时存在于左右两个子数组中。对于前两种情况,可以递归求解。
对于最后一种情况,需要独立考虑。因为必然跨越中点,所以子序中必然包含中点。所以从中点开始,分别向左向右搜寻最大的序列和。最后将左右最大序列号相加。

源代码

int maxSubArray(int* nums, int numsSize){
    return find_max_subarray(nums,0,numsSize - 1);
}

int find_max_subarray(int A[],int low,int high){
    int mid,left_sum,right_sum,cross_sum;
    if(low == high)
        return A[low];
    else{
        int mid = (low + high) / 2;
        left_sum = find_max_subarray(A,low,mid);
        right_sum = find_max_subarray(A,mid + 1,high);
        cross_sum = find_max_cross_subarray(A,low,mid,high);
    }
    if(left_sum >= right_sum && left_sum >= cross_sum)
        return left_sum;
    else if(right_sum >= left_sum && right_sum >= cross_sum)
        return right_sum;
    else
        return cross_sum;
}

int find_max_cross_subarray(int A[],int low,int mid,int high){
    int left_sum = A[mid];
    int sum = 0;
    for(int i = mid;i >= low;--i){
        sum = sum + A[i];
        if(sum > left_sum){
            left_sum = sum;
        }
    }
    int right_sum = A[mid + 1];
    sum = 0;
    for(int j = mid + 1;j <= high;++j){
        sum = sum + A[j];
        if(sum > right_sum){
            right_sum = sum;
        }
    }
    return (left_sum + right_sum);
}

分析

时间复杂度为O(nlgn),空间复杂度为常数级别(不包含递归时所开辟函数的栈空间)。

你可能感兴趣的:(最大子序和)