最大子序和

作者: Lularible | 来源:发表于2020-04-08 10:09 被阅读0次

    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),空间复杂度为常数级别(不包含递归时所开辟函数的栈空间)。

    相关文章

      网友评论

        本文标题:最大子序和

        本文链接:https://www.haomeiwen.com/subject/dzezphtx.html