[LeetCode] 918. Maximum Sum Circular Subarray 環形子數組的最大和



Given a circular array C of integers represented by `A`, find the maximum possible sum of a non-empty subarray of C.

Here, a circular array means the end of the array connects to the beginning of the array.  (Formally, C[i] = A[i] when 0 <= i < A.length, and C[i+A.length] = C[i] when i >= 0.)

Also, a subarray may only include each element of the fixed buffer A at most once.  (Formally, for a subarray C[i], C[i+1], ..., C[j], there does not exist i <= k1, k2 <= j with k1 % A.length = k2 % A.length.)

Example 1:

Input: [1,-2,3,-2]
Output: 3
Explanation: Subarray [3] has maximum sum 3

Example 2:

Input: [5,-3,5]
Output: 10 Explanation: Subarray [5,5] has maximum sum 5 + 5 = 10

Example 3:

Input: [3,-1,2,-1]
Output: 4
Explanation: Subarray [2,-1,3] has maximum sum 2 + (-1) + 3 = 4

Example 4:

Input: [3,-2,2,-3]
Output: 3 Explanation: Subarray [3] and [3,-2,2] both have maximum sum 3

Example 5:

Input: [-2,-3,-1]
Output: -1 Explanation: Subarray [-1] has maximum sum -1

Note:

  1. -30000 <= A[i] <= 30000
  2. 1 <= A.length <= 30000

這道題讓求環形子數組的最大和,對於環形數組,我們應該並不陌生,之前也做過類似的題目 [Circular Array Loop](http://www.cnblogs.com/grandyang/p/7658128.html),就是說遍歷到末尾之后又能回到開頭繼續遍歷。假如沒有環形數組這一個條件,其實就跟之前那道 [Maximum Subarray](http://www.cnblogs.com/grandyang/p/4377150.html) 一樣,解法比較直接易懂。這里加上了環形數組的條件,難度就增加了一些,需要用到一些 trick。既然是子數組,則意味着必須是相連的數字,而由於環形數組的存在,說明可以首尾相連,這樣的話,最長子數組的范圍可以有兩種情況,一種是正常的,數組中的某一段子數組,另一種是分為兩段的,即首尾相連的,可以參見 [大神 lee215 的帖子](https://leetcode.com/problems/maximum-sum-circular-subarray/discuss/178422/One-Pass) 中的示意圖。對於第一種情況,其實就是之前那道題 [Maximum Subarray](http://www.cnblogs.com/grandyang/p/4377150.html) 的做法,對於第二種情況,需要轉換一下思路,除去兩段的部分,中間剩的那段子數組其實是和最小的子數組,只要用之前的方法求出子數組的最小和,用數組總數字和一減,同樣可以得到最大和。兩種情況的最大和都要計算出來,取二者之間的較大值才是真正的和最大的子數組。但是這里有個 corner case 需要注意一下,假如數組中全是負數,那么和最小的子數組就是原數組本身,則求出的差值是0,而第一種情況求出的和最大的子數組也應該是負數,那么二者一比較,返回0就不對了,所以這種特殊情況需要單獨處理一下,參見代碼如下:
class Solution {
public:
    int maxSubarraySumCircular(vector<int>& A) {
        int sum = 0, mn = INT_MAX, mx = INT_MIN, curMax = 0, curMin = 0;
		for (int num : A) {
			curMin = min(curMin + num, num);
            mn = min(mn, curMin);
            curMax = max(curMax + num, num);
            mx = max(mx, curMax);
            sum += num;
		}
        return (sum - mn == 0) ? mx : max(mx, sum - mn);
    }
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/918


類似題目:

Maximum Subarray

Circular Array Loop


參考資料:

https://leetcode.com/problems/maximum-sum-circular-subarray/

https://leetcode.com/problems/maximum-sum-circular-subarray/discuss/178422/One-Pass


[LeetCode All in One 題目講解匯總(持續更新中...)](https://www.cnblogs.com/grandyang/p/4606334.html)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM