题目链接
英文链接: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 { |