JianZhiOffer_p31_GreatestSumOfSubarray

[笔试面试高频题]
求一个数组的子数组中所有元素和的最大值。
子数组指一个或连续多个数组成的数组。
使用动态规划方法求解,算法的时间复杂度为O(n).

举个栗子:
输入数组为:6,-3,-2,7,-15,1,2,2
和最大的子数组为:6,-3,-2,7
输出该子数组的和为:8

解法:

用curSum[i]表示前i个元素(包含第i个, i从0开始)所组成的子数组的最大和,那么max(curSum)就是所有子数组的最大和。

curSum[i] = curSum[i-1] + array[i],  if i == 0 || curSum[i-1] > 0 
          = array[i],                if i > 0 || curSum[i-1] < 0 

当前i-1个元素所组成的子数组的最大和为负数时,它与第i个元素之和一定比第i个元素小。此时,前i个元素所组成的子数组的最大和就是第i个元素的值。
当前i-1个元素所组成的子数组的最大和为正数时,它与第i个元素之和比第i个元素大。此时,前i个元素所组成的子数组的最大和为前i-1个元素所组成子数组的最大和加上第i个元素。

代码一:

class Solution {
public:
    bool invalidArray = false;
    int FindGreatestSumOfSubArray(vector<int> array) {
        int n = array.size();
        if (n < 1) {
            invalidArray = true;
            return 0;
        }
        vector<int> curSum(n,0);
        curSum[0] = array[0];
        for (auto i = 1; i<n; ++i) {
            if (curSum[i-1] > 0) {
                curSum[i] = array[i] + curSum[i-1];
            } else {
                curSum[i] = array[i];
            }
        }
        int maxSum = curSum[0];
        for (int i=1; i<n; ++i) {
            maxSum = curSum[i]>maxSum ? curSum[i]: maxSum;
        }
        return maxSum;
    }
}; // 时间复杂度O(n),空间复杂度O(n)

要找到所有子数组和中的最大和,每个元素至少需要遍历一边,因此算法的时间复杂度最少为O(n),已经是最优的了。

在上述代码中,我们用一个O(n)的额外空间curSum来存储前i个元素的子数组的最大和,但是程序最终只要一个最大值,因此可以考虑在计算curSum数组的过程中边计算边比较,即将第二个for循环放到第一个中执行,以此来节省空间复杂度。

代码二:

class Solution {
public:
    bool invalidArray = false;
    int FindGreatestSumOfSubArray(vector<int> array) {
        int n = array.size();
        if (n < 1) {
            invalidArray = true;
            return 0;
        }
        vector<int> curSum(n,0);
        curSum[0] = array[0];
        int maxSum = curSum[0];
        for (auto i = 1; i<n; ++i) {
            if (curSum[i-1] > 0) {
                curSum[i] = array[i] + curSum[i-1];
            } else {
                curSum[i] = array[i];
            }
            maxSum = curSum[i] > maxSum ? curSum[i]: maxSum;
        }
        return maxSum;
    }
}; // 时间复杂度O(n),空间复杂度O(1)

变量invalidArray用于在函数外检查输入的合法性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值