【算法题解】连续子数组的最大和

连续子数组的最大和

题目

输入一个 非空 整型数组,数组里的数可能为正,也可能为负。

数组中一个或连续的多个整数组成一个子数组。

求所有子数组的和的最大值。

要求时间复杂度为 O(n)。

数据范围

数组长度 [1,1000]。
数组内元素取值范围 [−200,200]。

样例
输入:[1, -2, 3, 10, -4, 7, 2, -5]

输出:18

解法1:动态规划

  • d p [ i ] dp[i] dp[i]为以 n u m s [ i ] nums[i] nums[i]为结尾的子数组中求和最大的子数组
  • 有两种可能的转移,一种不要 i i i前面的子数组,从 n u m s [ i ] nums[i] nums[i]开始为新的子数组;一种是和 n u m s [ i − 1 ] nums[i-1] nums[i1]以及其前面的数构成一个子数组,两种情况取max
  • 状态转移方程:

d p [ i ] = m a x { d p [ i − 1 ] + n u m s [ i ] n u m s [ i ] dp[i]=max\begin{cases} dp[i-1]+nums[i]\\ nums[i] \end{cases} dp[i]=max{ dp[i1]+nums[i]nums[i]

  • 答案:

max ⁡ 0 ≤ i ≤ n d p [ i ] \max_{0\le i\le n} dp[i] 0inmaxdp[i]

//dp
class Solution {
public:
    const int N=1005;
    int maxSubArray(vector<int>& nums) {
        int dp[N];
        int ans=-205;
        for(int i=0;i<nums.size();i++){
            dp[i]=nums[i];
            if(i)dp[i]=max(dp[i],dp[i-1]+nums[i]);
            ans=max(ans,dp[i]);
        }
        return ans;
    }
};

解法2:贪心

  • 考虑第 i i i个数 n u m s [ i ] nums[i] nums[i]的时候,用一个 s u m sum sum记录前 i − 1 i-1 i1个数累计的最大连续子数组合
  • 如果 s u m < 0 sum<0 sum<0则说明对子数组的求和没用贡献,可以丢弃,从 n u m s [ i ] nums[i] nums[i]开始新的子数组;否则则可以加上 s u m sum sum
  • 使用一个 a n s = max ⁡ i s u m i ans=\max_i sum_i ans=maxisumi记录答案,因为 s u m sum sum有可能在中间取得最大值随后又变小
  • 注意 a n s ans ans的初始化要从下界开始而不是 0 0 0
//贪心
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int sum=0,ans=-205;
        for(int i=0;i<nums.size();i++){
            if(sum<0) sum=nums[i];
            else sum+=nums[i];
            ans=max(ans,sum);
        }
        return ans;
    }
};

猜你喜欢

转载自blog.csdn.net/u011459717/article/details/128501244