239. 滑动窗口最大值
给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回滑动窗口中的最大值。
- 对于新的index,先判断当前的对头元素所指向位置是不是已经超出了本窗口,超出则删除队头
 - 如果新来的元素[index]比队尾大,while删除队尾(因为新加入的元素一定可以覆盖掉当前队尾可以覆盖的区间)
 - 加入当前index作为队尾
 - 将队头元素作为当前窗口的最大值出栈
class Solution {public int[] maxSlidingWindow(int[] nums, int k) {Deque<Integer> deque = new LinkedList<Integer>();int[] res = new int[nums.length-k+1];int l = 0;for(int i = 0 ; i < nums.length;i++) {if(deque.size()>0 && i -k + 1 > deque.peekFirst()) deque.removeFirst();while(deque.size()>0 && nums[deque.peekLast()] <= nums[i]) deque.pollLast();deque.offerLast(i);if(i-k+1>=0) res[l++] = nums[deque.peekFirst()];}return res;}}
 
918. 环形子数组的最大和
给定一个由整数数组 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)
- 使用一个两倍长度的前缀和数组
 对于i位置的前缀和,减去前面单倍长度的区间中前缀和的最小值
class Solution {public int maxSubarraySumCircular(int[] A) {int max = -30000 -1;int[] s = new int[A.length*2];s[0] = A[0];for(int i =0 ; i < A.length;i++) {max = Math.max(max,A[i]);s[i] = s[i+A.length]= A[i];}for(int i = 1 ; i < s.length;i++) {s[i] = s[i-1] + s[i];}Deque<Integer> q = new LinkedList<>();int len = A.length-1;for(int i = 0 ; i < s.length ; i++) {if(q.size()>0) {max = Math.max(s[i]-s[q.getFirst()],max);}if(q.size()>0 && i-len>q.getFirst()) q.pollFirst();while(q.size() >0 && s[q.getLast()]>=s[i]) q.pollLast();q.addLast(i);}return max;}}
