子数组之和最大值

问题描述

给定一个序列 A 0 A_0 A0 A 1 A_1 A1 A 2 A_2 A2、…、 A n − 1 A_{n-1} An1,求 A i + A i + 1 + . . . + A j A_i+A_{i+1}+...+A_j Ai+Ai+1+...+Aj的最大值。

解一

暴力枚举左端点 i i i和右端点 j j j,之后计算 A i A_i Ai A j A_j Aj之间的和,时间复杂度 O ( n 3 ) O(n^3) O(n3),很容易TLE。

#define INF 0x7FFFFFFF

int sub_sum(int a[],int n)
{
	int MAX = -INF;
	for(int i = 0;i < n;i++)
	{
		for (int j = i; j < n; j++)
 		 {
   			int temp = 0;
   			for (int k = i; k <= j; k++)
  			{
    				temp += a[k];
  			}
   			if (temp > MAX)
   			{
   				MAX = temp;
   			}
 		 }
	}
	return MAX;
}

解二

输入数据时记录前缀和,预处理 s u m [ i ] = A [ 0 ] + . . . + A [ i ] sum[i] = A[0] + ... + A[i] sum[i]=A[0]+...+A[i],因此 A i + A i + 1 + . . . + A j = s u m [ j ] − s u m [ i − 1 ] A_i+A_{i+1}+...+A_j=sum[j]-sum[i-1] Ai+Ai+1+...+Aj=sum[j]sum[i1],复杂度优化为 O ( n 2 ) O(n^2) O(n2)

int sub_sum(int a[],int n)
{
	int MAX = -INF;
	for(int i = 0;i < n;i++)
	{
		for(int j = i;j < n;j++}
		{
			int temp = sum[j] - sum[i - 1];
			if(temp > MAX)
				MAX = temp;
			else
				temp = 0;
		}
	}
	return MAX;
}

解三

动态规划,复杂度 O ( n ) O(n) O(n)
定义状态数组 d p [ i ] dp[i] dp[i],表示以 A [ i ] A[i] A[i]结尾的连续序列的最大和,这样就只有两种情况:
1,该连续序列只有 A [ i ] A[i] A[i]这一个元素;
2,该序列有多个元素,从之前的 A [ p ] A[p] A[p]开始,到 A [ i ] A[i] A[i]结束。
对于1,最大和就是 A [ i ] A[i] A[i]
对于2,最大和是 d p [ i − 1 ] + A [ i ] dp[i - 1]+A[i] dp[i1]+A[i],因为 d p [ i ] dp[i] dp[i]要求以 A [ i ] A[i] A[i]结尾,所以即使 A [ i ] A[i] A[i]为负数, d p [ i ] dp[i] dp[i]仍然等于 d p [ i − 1 ] + A [ i ] dp[i - 1]+A[i] dp[i1]+A[i]
所以状态转移方程就是:
d p [ i ] = m a x { A [ i ] , d p [ i − 1 ] + A [ i ] } dp[i]=max{\{A[i],dp[i-1]+A[i]\}} dp[i]=max{A[i],dp[i1]+A[i]}边界是 d p [ 0 ] = A [ 0 ] dp[0]=A[0] dp[0]=A[0]
所以枚举 i i i,得到 d p dp dp数组,求出 d p dp dp数组最大值即可。

可以看到,每次计算 d p [ i ] dp[i] dp[i]只用到 d p [ i − 1 ] dp[i-1] dp[i1],不直接用到之前的信息,这就是状态的无后效性,只有这样,动态规划才可能得到正确结果。

int dp[5010];
dp[0] = a[0];

int sub_sum(int a[],int n)
{
	for(int i = 1;i < n;i++)
	{
		//状态转移方程
		dp[i] = max(a[i],dp[i - 1] + a[i]);
	}

	int k = 0;
	for(int i = 1;i < n;i++)
	{
		if(dp[i] > dp[k])
			k = i;
	}
	return dp[k];
}

为了避免使用 d p [ ] dp[] dp[]数组,可以将空间复杂度优化为 O ( 1 ) O(1) O(1)

class Solution {
public:
    int maxSubArray(vector& nums) {
        int allSum = INT_MIN, curSum = 0;
        
        int n = nums.size();
        for(int i = 0;i < n;i++)
        {
            curSum = max(nums[i], curSum + nums[i]);
            if(curSum > allSum)
            {
                allSum = curSum;
            }
        }
        
        return allSum;
    }
};

你可能感兴趣的:(算法)