JZ85 连续子数组的最大和(二)

题目描述

输入一个长度为n的整型数组array,数组中的一个或连续多个整数组成一个子数组,找到一个具有最大和的连续子数组。

1.子数组是连续的,比如[1,3,5,7,9]的子数组有[1,3],[3,5,7]等等,但是[1,3,7]不是子数组

2.如果存在多个最大和的连续子数组,那么返回其中长度最长的,该题数据保证这个最长的只存在一个

3.该题定义的子数组的最小长度为1,不存在为空的子数组,即不存在[]是某个数组的子数组

4.返回的数组不计入空间复杂度计算

方法一:动态规划方法

解题思路

对于本题目的求解,我们使用动态规划的方法进行求解,状态转移方程为dp[i]=max(dp[i1]+array[i],array[i])dp[i] = max(dp[i-1] + array[i], array[i]),并且我们使用left和right记录子区间的起始位置,最后输出结果。

alt

解题代码

class Solution {
public:
    vector<int> FindGreatestSumOfSubArray(vector<int>& array) {
        vector<int> res;
        vector<int> dp(array.size(), 0); //记录到下标i为止的最大连续子数组和
        dp[0] = array[0];
        int maxsum = dp[0];
        int left = 0, right = 0; //滑动区间
        int resl = 0, resr = 0; //记录最长的区间
        for(int i = 1; i < array.size(); i++)
        {
            right++;
            dp[i] = max(dp[i - 1] + array[i], array[i]); //状态转移:连续子数组和最大值
            if(dp[i - 1] + array[i] < array[i]) //区间新起点
                left = right;
            if(dp[i] > maxsum || dp[i] == maxsum && (right - left + 1) > (resr - resl + 1))
            { //更新最大值
                maxsum = dp[i];
                resl = left;
                resr = right;
            }
        }
        for(int i = resl; i <= resr; i++) //取数组
            res.push_back(array[i]);
        return res;
    }
};

复杂度分析

时间复杂度:一层循环,因此时间复杂度为O(N)O(N)

空间复杂度:辅助数组长度为n,因此空间复杂度为O(N)O(N)

方法二:优化算法

解题思路

基于方法一,我们以变量代替辅助数组,在状态转移时更新变量b,然后其他按照方法一进行结果输出。

alt

解题代码

class Solution {
public:
    vector<int> FindGreatestSumOfSubArray(vector<int>& array) {
        vector<int> res;
        int a = array[0];
        int b = 0;
        int maxsum = a;
        int left = 0, right = 0; //滑动区间
        int resl = 0, resr = 0; //记录最长的区间
        for(int i = 1; i < array.size(); i++)
        {
            right++;
            b = max(a + array[i], array[i]); //状态转移:连续子数组和最大值
            if(a + array[i] < array[i]) //区间新起点
                left = right;
            if(b > maxsum || b == maxsum && (right - left + 1) > (resr - resl + 1))
            { //更新最大值
                maxsum = b;
                resl = left;
                resr = right;
            }
            a = b; //更新x的状态
        }
        for(int i = resl; i <= resr; i++) //取数组
            res.push_back(array[i]);
        return res;
    }
};

复杂度分析

时间复杂度:一层循环,因此时间复杂度为O(N)O(N)

空间复杂度:常数级变量空间,因此空间复杂度为O(1)O(1)