目录链接:
力扣编程题-解法汇总_分享+记录-CSDN博客
GitHub同步刷题项目:
https://github.com/September26/java-algorithms
原题链接:力扣
描述:
给定一个长度为 n
的环形整数数组 nums
,返回 nums
的非空 子数组 的最大可能和 。
环形数组 意味着数组的末端将会与开头相连呈环状。形式上, nums[i]
的下一个元素是 nums[(i + 1) % n]
, nums[i]
的前一个元素是 nums[(i - 1 + n) % n]
。
子数组 最多只能包含固定缓冲区 nums
中的每个元素一次。形式上,对于子数组 nums[i], nums[i + 1], ..., nums[j]
,不存在 i <= k1, k2 <= j
其中 k1 % n == k2 % n
。
示例 1:
输入:nums = [1,-2,3,-2] 输出:3 解释:从子数组 [3] 得到最大和 3
示例 2:
输入:nums = [5,-3,5] 输出:10 解释:从子数组 [5,5] 得到最大和 5 + 5 = 10
示例 3:
输入:nums = [3,-2,2,-3] 输出:3 解释:从子数组 [3] 和 [3,-2,2] 都可以得到最大和 3
提示:
n == nums.length
1 <= n <= 3 * 104
-3 * 104 <= nums[i] <= 3 * 104
解题思路:
* 解题思路: * 首先,我们把nums的长度增加一倍,并且求其前缀和。 * 这样这题就变成了一个在2n的数组中,找i>j,且i<=j+n,prefixs[i]-prefixs[j]的最大值的题目。 * 首先,求前缀和,对应方法maxSubarraySumCircular,求prefixs[i]-prefixs[j]的最大值对应方法findBixDiff。 * findBixDiff方法中,构造单调队列,分为三种场景: * 1。如果i-j的长度大于n,则j需要被移除。 * 2。如果prefixs[i]-prefixs[j]>abs,则更新abs。 * 3。如果prefixs[i]<=prefixs[k],则队列中k位置的丧失意义,因为i的位置更靠后,并且值更小,比k更具有优势,因此k出列 * 最后返回abs即可。
代码:
public class Solution918 {
// -2,1,-3,4,-1,2,1,-5,4
public int maxSubarraySumCircular(int[] nums) {
int n = nums.length;
List<Integer> prefixs = new ArrayList<>();
prefixs.add(0);
int pre = prefixs.get(0);
for (int i = 0; i < n * 2; i++) {
pre += nums[i % n];
prefixs.add(pre);
}
return findBixDiff(prefixs, n);
}
public int findBixDiff(List<Integer> list, int size) {
int abs = Integer.MIN_VALUE;
Deque<Pair<Integer, Integer>> deque = new ArrayDeque<>();
deque.push(new Pair<>(0, list.get(0)));
for (int i = 1; i < list.size(); i++) {
if (!deque.isEmpty() && i - deque.peekFirst().getKey() > size) {
deque.pollFirst();
}
Integer integer = list.get(i);
abs = Math.max(integer - deque.peekFirst().getValue(), abs);
while (!deque.isEmpty() && deque.peekLast().getValue() >= integer) {
deque.pollLast();
}
deque.offerLast(new Pair<>(i, integer));
}
return abs;
}
}