这个题目实话我第一次没有想出来,只能玩尬的过一点用例,因为我还没系统地学习动态规划以及贪心算法。
这里的题解主要参考官方的题解-逐级优化:
1.第一级:暴力做法-时间复杂度O( n 3 n^3 n3),空间复杂度O(1)
枚举左右端点然后计算总和,并实时更新最大的和。
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++)//计算区间和-最原始的写法不同于python那么多库
{
now += array[k];
}
ans = max(now, ans);//更新ans
}
}
return ans;
}
};
第二级-优化上述算法-因为上面的过程会重复计算很多子空间的总和,使用前缀和优化,用空间(定义一个新的数组存储和)换时间。
时间复杂度 O ( n 2 ) O(n^2) O(n2) 空间复杂度 O ( n ) O(n) O(n)
写出一个优化方程:
s u m [ 1 , j ] − s u m [ 1 , i − 1 ] = = s u m [ i , j ] sum[1,j]-sum[1,i-1]==sum[i,j] sum[1,j]−sum[1,i−1]==sum[i,j]
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.最高级-动态规划
动态规划还是讲究一个逆向思维,从最后一个数入手去推演前面已经有的和的正负需要满足什么条件。而不是去分析每一个遍历的数的正负。
算法思路:
1.设dp[n]为以第n个数为结尾,得到的子数组的和的最大值
2.因为以第n个数为结尾所以array[n]是必然被选择的
3.基于dp[n-1]的值,如果dp[n-1]>0,我们加上这个正数,我们的值是不是必然会增大
4.如果dp[n-1]<0,那么我们加上负数,我们的值就会减小,这个时候我们不如不要前面的结果,只要当前这个数,结果反而更优
5.于是我们就得到了状态转移方程 d p [ n ] = a r r a y [ n ] + ( d p [ n − 1 ] > 0 ? d p [ n − 1 ] : 0 ) dp[n]=array[n]+(dp[n-1]>0?dp[n-1]:0) dp[n]=array[n]+(dp[n−1]>0?dp[n−1]:0)(?:就是if-else的意思),实时跟ans比较,更新最大值即可
6.定义一个dp数组,时间复杂度 O ( n ) O(n) O(n),空间复杂度 O ( n ) O(n) O(n)–定义了一个dp数组
优化:
1.我们可以发现当前状态只跟上一个状态有关,所以我们可以只用一个int来代替dp数组,即sum
2.如果sum<0,那么这个时候就sum=array[i]
3.如果sum>0,那么就sum=sum+array[i]
4.然后实时跟allsum比较,更新最大值即可
5.时间复杂度 O ( n ) O(n) O(n) ,空间复杂度 O ( 1 ) O(1) O(1)
class Solution {
public:
int FindGreatestSumOfSubArray(vector<int> array) {
int sum=0;
int allsum=INT_MIN;//全是负的就是玩尬的
for(int i=0;i<array.size();i++){ //java size--python shape??
if(sum<0){
sum=array[i];
}
else{
sum+=array[i]; //逐级叠加
}
allsum=max(sum,allsum);//更新allsum
}
return allsum;
}
};