Description
Given a circular integer array nums of length n, return the maximum possible sum of a non-empty subarray of nums.
A circular array means the end of the array connects to the beginning of the array. Formally, the next element of nums[i] is nums[(i + 1) % n] and the previous element of nums[i] is nums[(i - 1 + n) % n].
A subarray may only include each element of the fixed buffer nums at most once. Formally, for a subarray nums[i], nums[i + 1], …, nums[j], there does not exist i <= k1, k2 <= j with k1 % n == k2 % n.
Example 1:
Input: nums = [1,-2,3,-2]
Output: 3
Explanation: Subarray [3] has maximum sum 3.
Example 2:
Input: nums = [5,-3,5]
Output: 10
Explanation: Subarray [5,5] has maximum sum 5 + 5 = 10.
Example 3:
Input: nums = [-3,-2,-3]
Output: -2
Explanation: Subarray [-2] has maximum sum -2.
Constraints:
n == nums.length
1 <= n <= 3 * 10^4
-3 * 104 <= nums[i] <= 3 * 10^4
Solution
Solved after reading others’ solutions…
For circular lists, the max subarray lies either in the middle of the list, or be split.
So to solve case2, instead of finding the max subarray, we could try to find the minimum subarray.
Only one special case, if all the elements in the array are negative, then we would get the minimum subarray as the whole list. So we need to deal with that.
Time complexity:
o
(
n
)
o(n)
o(n)
Space complexity:
o
(
1
)
o(1)
o(1)
Code
class Solution:
def max_subarray(self, nums: list) -> int:
dp = nums[0]
res = nums[0]
for each_num in nums[1:]:
dp = max(dp, 0) + each_num
res = max(dp, res)
return res
def min_subarray(self, nums: list) -> int:
dp = nums[0]
res = nums[0]
for each_num in nums[1:]:
dp = each_num + min(dp, 0)
res = min(res, dp)
return res
def maxSubarraySumCircular(self, nums: List[int]) -> int:
num_sum = sum(nums)
ans1 = self.max_subarray(nums)
ans2 = num_sum - self.min_subarray(nums)
return max(ans1, ans2) if ans2 != 0 else ans1