算法设计与分析(二):Divide And Conquer

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.

题目求一个数组中和最大的子数组。第一时间我们可以想到的就是直接遍历。因为只需要求值而不需要知道是哪个子数组,所以求出数组中所有子数组的和,然后取最大值即可。
采用嵌套循环的方式,该算法的时间复杂度应该为O(n^2)(算法很简单,此处不给出了)。

这个方法虽然思路简单,但是明显不是最优解。那么有没有更好的方法呢?


我们思考一下之前提到过的分而治之思想。如何把问题转化成一个相同问题的累计?

首相想到的是求在下标i到j之间的最小子数组:max(num,i,j);但是如果将问题这么分析,那么问题无法再往下分割,一步步简化;

这里想到要求和,当然是一个个的数加起来。求和的最大值,当然要每次做加法都要越加越大:即,每次都是一个大于零的数。所以,将问题转化成max(num,j),即求以下标为j的数结尾的数组的子数组的最大值,也就是:
max(num,j) = max(num,j-1)>0 ? max(num,j-1)+num[j] : num[j]

每次的问题求最大和都是求上一次的最大和,也就是只要知道了第一次的最大和max(num,0),也就是num[0],整个数组的子数组最大和也就可以得知了。

c代码如下:

int maxSubArray(int* nums, int numsSize) {
    int sum[numsSize];
    sum[0] = nums[0];
    int max = sum[0];

    for(int i = 1;i < numsSize; i ++) {
        sum[i] = nums[i] + ((sum[i-1] > 0) ? sum[i-1] : 0);
        max = (max > sum[i]) ? max : sum[i];
    }

    return max;
}

附上LeetCode链接:https://leetcode.com/problems/maximum-subarray/description/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值