題目爲:給你一個整數數組,返回它的某個 非空子數組(連續元素)在執行一次可選的刪除操作後,所能得到的最大元素總和。
換句話說,你可以從原數組中選出一個子數組,並可以決定要不要從中刪除一個元素(只能刪一次哦),(刪除後)子數組中至少應當有一個元素,然後該子數組(剩下)的元素總和是所有子數組之中最大的。
注意,刪除一個元素後,子數組 不能爲空。
題目分析:即動態規劃的最基本題型”連續子數組的最大和“的升級版,可以刪除子數組的一個元素再進行比較,得出最大值。
題目重點:重點在於如何刪除一個元素,如果單純選擇子數組的最小值那麼就回歸到了O(n2)的複雜度上了,技巧是通過左右連續子數組求夾逼的方式來完成刪除一個元素的操作。
詳細思路:連續子數組的最大和的遞歸式是 dp[i]=max(dp[i-1]+arr[i],arr[i]),即判斷dp[i-1]是否大於0。本題目比這個式子略複雜,需要求左右連續子數組的最大值,故遞歸式爲
dp[i]=Ldp[i-1]+Rdp[i+1]; //相隔一個元素
Ldp[i]=max(Ldp[i-1]+arr[i],arr[i]);//左側求連續子數組的最大和
Rdp[i]=max(Rdp[i+1]+arr[i],arr[i]);//右側求連續子數組的最大和
代碼如下:
class Solution {
public:
int maximumSum(vector<int>& arr) {
int as=arr.size();
vector<int> l(as,0);
vector<int> r(as,0);
int max0,max1;
l[0]=arr[0];
max0=l[0];
for(int i=1;i<as;i++)
{
l[i]=max(l[i-1]+arr[i],arr[i]);
max0=max(l[i],max0);
}
r[as-1]=arr[as-1];
for(int i=as-2;i>=0;i--)
{
r[i]=max(r[i+1]+arr[i],arr[i]);
}
max1=max0;
for(int i=1;i<as-1;i++)//insert minus one
{
max1=max(l[i-1]+r[i+1],max1);
}
return max1;
}
};
其中max0爲不刪除元素的最大值,即連續子數組的最大值,max1爲刪除一個元素的連續子數組的最大值。