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:
-30000 <= A[i] <= 30000
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
類似題目:
參考資料:
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)