题目链接
英文链接:https://leetcode.com/problems/maximum-sum-circular-subarray/
中文链接:https://leetcode-cn.com/problems/maximum-sum-circular-subarray/
题目详述
给定一个由整数数组 A 表示的环形数组 C,求 C 的非空子数组的最大可能和。
在此处,环形数组意味着数组的末端将会与开头相连呈环状。(形式上,当0 <= i < A.length 时 C[i] = A[i],而当 i >= 0 时 C[i+A.length] = C[i])
此外,子数组最多只能包含固定缓冲区 A 中的每个元素一次。(形式上,对于子数组 C[i], C[i+1], ..., C[j],不存在 i <= k1, k2 <= j 其中 k1 % A.length = k2 % A.length)
示例 1:
| 1 | 输入:[1,-2,3,-2] | 
示例 2:
| 1 | 输入:[5,-3,5] | 
示例 3:
| 1 | 输入:[3,-1,2,-1] | 
示例 4:
| 1 | 输入:[3,-2,2,-3] | 
示例 5:
| 1 | 输入:[-2,-3,-1] | 
提示:
- -30000 <= A[i] <= 30000
- 1 <= A.length <= 30000
题目详解
方法一:前缀和+单调队列。
- 先将数组扩充一倍来模拟环状数组,然后求数组的前缀和。
- 对以下标 i 结尾的子数组,其最优为 sum[i] - min(sum[j]), i - n <= j < i。
- 为了快速知道当前组子数组的最小值,可以运用单调队列,保持队列从队头到队尾单调递增。
- 遍历数组,队列长度超过限制则队首元素出队,进行结算,保持队列单调后当前元素入队。
| 1 | public class LeetCode_00918 { | 
方法二:动态规划。
- 如果不存在环形则本题就是 LeetCode53-最大子序和。
- 存在环形则说明最大子数组可能存在于首尾相连的子数组中,可以间接求得此值,通过元素总和减去最小子数组总和。
- 结果就是这二者取最大值。
- 存在一个特殊情况:所有元素不为正数,结果就是数组中最大的那个数,即 maxSum。
- 因而,最终的结果为 maxSum > 0 ? Math.max(maxSum, tot - minSum) : maxSum。
| 1 | public class LeetCode_00918 { |