剑指offer(C++)-JZ42:连续子数组的最大和(算法-动态规划)

作者:翟天保Steven
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

题目描述:

输入一个长度为n的整型数组array,数组中的一个或连续多个整数组成一个子数组,子数组最小长度为1。求所有子数组的和的最大值。

数据范围:

1<=n<=2×105

0<=a[i]<=100

要求:时间复杂度为 O(n),空间复杂度为 O(n)

进阶:时间复杂度为 O(n),空间复杂度为 O(1)

示例:

输入:

[1,-2,3,10,-4,7,2,-5]

返回值:

18

说明:

经分析可知,输入数组的子数组[3,10,-4,7,2]可以求得最大和为18

解题思路:

本题考察算法-动态规划算法的使用。用两种动态规划的解法。

解法一:使用常规的动态规划思路:用一个vector-dp存储到各个下标时的最大连续子数组和,进行一轮遍历,若dp[i-1]+array[i]比array[i]大,说明到前一下标为止的最大连续子数组,可以把当前下标纳入到该连续子数组中;反之,则以array[i]为新的起点,继续向后扩展连续子数组;与此同时,动态刷新最大值maxsum。

解法二:对空间复杂度进行优化:常规解法使用vector来记录各个下标的最大连续子数组和,但本题目的要求并没有需要读取vector中信息,因此该vector可以优化掉。用x代替dp[i-1],相当于当前下标前的最大连续子数组和,其他的同解法一一致,这样vector的空间就节省下来了。

测试代码:

解法一:动态规划

class Solution {
  public:
    int FindGreatestSumOfSubArray(vector<int> array) {
        // 记录到下标i为止的最大连续子数组和
        vector<int> dp(array.size(), 0);
        dp[0] = array[0];
        int maxsum = dp[0];
        for (int i = 1; i < array.size(); i++) {
            // 确定到当前下标为止时的连续子数组和最大值
            dp[i] = max(dp[i - 1] + array[i], array[i]);
            // 刷新最大值
            maxsum = max(maxsum, dp[i]);
        }
        return maxsum;
    }
};

解法二:动态规划进阶

class Solution {
public:
    int FindGreatestSumOfSubArray(vector<int> array) {
        int x = array[0];
        int maxsum = x;
        for(int i = 1; i < array.size(); i++){
            // 确定到当前下标为止时的连续子数组和最大值
            x = max(x + array[i], array[i]); 
            // 刷新最大值
            maxsum = max(maxsum, x); 
        }
        return maxsum;
    }
};

猜你喜欢

转载自blog.csdn.net/zhaitianbao/article/details/127064441