题目陈述
题目大意:给定一个有正数有负数的数组,求解连续的一段的元素的和的最大值
算法1:暴力做法
算法思路
枚举左右端点,然后计算这个区间的总和now,跟ans比较,如果比ans大,则更新ans,最后循环结束返回ans
时间复杂度
,空间复杂度
代码实现
class Solution { public: int FindGreatestSumOfSubArray(vector<int> array) { int ans = INT_MIN; int len = array.size(); for (int i = 0; i < len; i++)//枚举左端点 { for (int j = i; j < len; j++)//枚举右端 { int now = 0; for (int k = i; k <= j; k++)//计算区间和 { now += array[k]; } ans = max(now, ans);//更新ans } } return ans; } };
算法2:前缀和优化
算法思路
我们发现上面的过程中,会重复计算很多的子区间的总和,所以我们用前缀和优化,
第一个数到第j个数的和,减去第一个数到第i-1个数的和,即得到第i个数到第j个数的和,即
时间复杂度
,空间复杂度
(因为定义了一个sum数组)
代码实现
class Solution{ public: int FindGreatestSumOfSubArray(vector<int> array) { int ans=INT_MIN; int len = array.size(); vector<int> sum(len+1,0); //sum[0]设为空集, //sum[i+1]设为array[0,i]的和,其中i=0~len-1 //约定array[-1]==0为空集 for(int i=0;i<len;i++){ sum[i+1]=sum[i]+array[i];//计算前缀和 } for (int i = 0; i < len; i++)//约定array[-1]==0为空集 { for (int j = i+1; j <= len; j++) { ans=max(ans,sum[j]-sum[i]);//计算[i-1,j-1]的和 } } return ans; }; };
算法3:动态规划
算法思路
设dp[n]为以第n个数为结尾,得到的子数组的和的最大值
因为以第n个数为结尾所以array[n]是必然被选择的
基于dp[n-1]的值,如果dp[n-1]>0,我们加上这个正数,我们的值是不是必然会增大
如果dp[n-1]<0,那么我们加上负数,我们的值就会减小,这个时候我们不如不要前面的结果,只要当前这个数,结果反而更优
于是我们就得到了状态转移方程
dp[n]=array[n]+(dp[n-1]>0?dp[n-1]:0)
,实时跟ans比较,更新最大值即可时间复杂度
,空间复杂度
(定义了一个dp数组)
优化算法(空间复杂度)
我们可以发现当前状态只跟上一个状态有关,所以我们可以只用一个int来代替dp数组,即num
如果num<0,那么这个时候就num=array[i]
如果num>0,那么就num=num+array[i]
然后实时跟ans比较,更新最大值即可
时间复杂度
,空间复杂度
动画演示
代码实现
C++
class Solution { public: int FindGreatestSumOfSubArray(vector<int> array) { int now, ans; now = 0, ans = INT_MIN; for (int i = 0; i < array.size(); i++) { if (now < 0)//now<0,则舍去前面的 now = array[i]; else { now += array[i];//比0大则直接加上去 } ans = max(now, ans);//更新ans } return ans; } };
python
class Solution: def FindGreatestSumOfSubArray(self, array): now=0 ans=-1000000000 for i in array:#此处i即代表array里面的第i个元素的值 if now<0 : now=i#now<0,则舍去前面的 else : now+=i ans=max(ans,now)#更新ans return ans