【線性 dp】B012_LC_K 次串聯後最大子數組之和(最大前後綴和 + 最大子數組 + 分類討論)

一、Problem

給你一個整數數組 arr 和一個整數 k。首先,我們要對該數組進行修改,即把原數組 arr 重複 k 次。

舉個例子,如果 arr = [1, 2] 且 k = 3,那麼修改後的數組就是 [1, 2, 1, 2, 1, 2]。然後,請你返回修改後的數組中的最大的子數組之和。

注意,子數組長度可以是 0,在這種情況下它的總和也是 0。由於 結果可能會很大,所以需要 模(mod) 10^9 + 7 後再返回。

輸入:arr = [1,-2,1], k = 5
輸出:2

提示:

1 <= arr.length <= 10^5
1 <= k <= 10^5
-10^4 <= arr[i] <= 10^4

二、Solution

方法一:最大前後綴

最暴力的方法是遍歷 n × k 次,遍歷時通過對數組下標進行取模防止出界,實時記錄子數組最大和,但會超時。這裏分類討論一下 kk 的情況:

  • k=1k = 1,直接求子數組最大和 mSum
  • k=2k = 2,答案可能由兩個數組的最大後綴和 + 最大前綴和組成
  • k>2k > 2
    • 如果 tot<0tot < 0tottot 爲數組總和),那麼假如數組 a 爲 [x1,x2,x3],那麼拼接之後變爲:
      [x1,x2,x3,x1,x2,x3,x1,x2,x3,x1,x2,x3],因爲 sum < 0,所以 [x1,x2,x3,x1,x2,x3,x1,x2,x3,x1,x2,x3] 加粗的這一段總和也 < 0,所以當 k > 2 && sum < 0 時,考慮加入中間那一段和就不可能形成爲答案了。
    • 如果 sum0sum \geqslant 0,中間那一段顯然可以被考慮進來,且它的總和可以很方便計算出來:(k2)×mSum(k - 2) × mSum,此時在類加上最大前後綴和即爲答案。

最後要計算的量羅列一下:最大後綴和 mSuf、最大前綴和 mPre、最大子數組和 mSum

class Solution {
    public int kConcatenationMaxSum(int[] a, int k) {
        int n = a.length, mod = (int) 1e9+7, mSum = a[0], mPre = a[0], mSuf = a[n-1];
        int cur = 0, pre = 0, suf = 0;
        
        for (int i = 0; i < n; i++) {
            cur = cur > 0 ? (cur + a[i]) % mod : a[i];  //cur<=0的話,無論加上整數還是負數,都不會比直接用a[i]大
            mSum = Math.max(mSum, cur);    //最大子數組和

            pre = (pre + a[i]) % mod;
            suf = (suf + a[n-i-1]) % mod;
            mPre = Math.max(mPre, pre);    //最大前綴和
            mSuf = Math.max(mSuf, suf);    //最大後綴和
        }
        mPre = Math.max(0, mPre);
        mSuf = Math.max(0, mSuf);
        mSum = Math.max(0, mSum);
        int tot = pre, ans = 0;
        
        if (k == 1)
            ans = mSum;
        else if (k == 2)
            ans = Math.max(mSum, (mPre + mSuf) % mod);
        else {
            if (tot <= 0) {
                ans = Math.max(mSum, (mPre + mSuf) % mod);
            } else {
                long t = ((long) (k-2)*tot%mod + mPre + mSuf) % mod;	//這裏的乘法可能會導致溢出
                ans = Math.max((int) t, mSum);
            }
        }
        return ans;
    }
}

複雜度分析

  • 時間複雜度:O(n)O(n)
  • 空間複雜度:O(1)O(1)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章