一、Problem
給你一個整數數組,返回它的某個 非空 子數組(連續元素)在執行一次可選的刪除操作後,所能得到的最大元素總和。
換句話說,你可以從原數組中選出一個子數組,並可以決定要不要從中刪除一個元素(只能刪一次哦),(刪除後)子數組中至少應當有一個元素,然後該子數組(剩下)的元素總和是所有子數組之中最大的。
注意,刪除一個元素後,子數組 不能爲空。
輸入:arr = [1,-2,0,3]
輸出:4
解釋:我們可以選出 [1, -2, 0, 3],然後刪掉 -2,這樣得到 [1, 0, 3],和最大。
輸入:arr = [1,-2,-2,3]
輸出:3
解釋:我們直接選出 [3],這就是最大和。
二、Solution
方法一:dp
- 定義狀態:
- 表示以 結尾且沒刪過元素的子數組最大總和
- 表示以 結尾且刪除過元素的子數組最大總和
- 思考初始化:
- 思考狀態轉移方程:
- 要麼接着前一段,要麼新開一段。
- 要麼接着前一段;要麼刪除 就此斷開。
- 思考輸出:
class Solution {
public int maximumSum(int[] a) {
int n = a.length, INF = (int) -2e5, max = a[0], f[][] = new int[n][2];
f[0][0] = a[0];
f[0][1] = 0;
for (int i = 1; i < n; i++) {
f[i][0] = Math.max(a[i], f[i-1][0] + a[i]);
f[i][1] = Math.max(f[i-1][0], f[i-1][1] + a[i]);
max = Math.max(max, Math.max(f[i][0], f[i][1]));
}
return max;
}
}
複雜度分析
- 時間複雜度:,
- 空間複雜度:,
方法二:空間壓縮
可以進行空間壓縮,因爲 f[i][0] 和 f[i][1] 只與前前一個狀態有關
class Solution {
public int maximumSum(int[] a) {
int n = a.length, max = a[0];
int fi_0 = a[0], fi_1 = 0;
for (int i = 1; i < n; i++) {
int pre_fi_0 = fi_0;
fi_0 = Math.max(fi_0 + a[i], a[i]);
fi_1 = Math.max(fi_1 + a[i], pre_fi_0);
max = Math.max(max, Math.max(fi_0, fi_1));
}
return max;
}
}
複雜度分析
- 時間複雜度:,
- 空間複雜度:,