239. 滑动窗口最大值

给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回滑动窗口中的最大值。
image.png

  • 对于新的index,先判断当前的对头元素所指向位置是不是已经超出了本窗口,超出则删除队头
  • 如果新来的元素[index]比队尾大,while删除队尾(因为新加入的元素一定可以覆盖掉当前队尾可以覆盖的区间)
  • 加入当前index作为队尾
  • 将队头元素作为当前窗口的最大值出栈
    1. class Solution {
    2. public int[] maxSlidingWindow(int[] nums, int k) {
    3. Deque<Integer> deque = new LinkedList<Integer>();
    4. int[] res = new int[nums.length-k+1];
    5. int l = 0;
    6. for(int i = 0 ; i < nums.length;i++) {
    7. if(deque.size()>0 && i -k + 1 > deque.peekFirst()) deque.removeFirst();
    8. while(deque.size()>0 && nums[deque.peekLast()] <= nums[i]) deque.pollLast();
    9. deque.offerLast(i);
    10. if(i-k+1>=0) res[l++] = nums[deque.peekFirst()];
    11. }
    12. return res;
    13. }
    14. }

918. 环形子数组的最大和

给定一个由整数数组 A 表示的环形数组 C,求 **C** 的非空子数组的最大可能和。
在此处,环形数组意味着数组的末端将会与开头相连呈环状。(形式上,当0 <= i < A.lengthC[i] = A[i],且当 i >= 0C[i+A.length] = C[i]
此外,子数组最多只能包含固定缓冲区 A 中的每个元素一次。(形式上,对于子数组 C[i], C[i+1], ..., C[j],不存在 i <= k1, k2 <= j 其中 k1 % A.length = k2 % A.length
image.png

  • 使用一个两倍长度的前缀和数组
  • 对于i位置的前缀和,减去前面单倍长度的区间中前缀和的最小值

    1. class Solution {
    2. public int maxSubarraySumCircular(int[] A) {
    3. int max = -30000 -1;
    4. int[] s = new int[A.length*2];
    5. s[0] = A[0];
    6. for(int i =0 ; i < A.length;i++) {
    7. max = Math.max(max,A[i]);
    8. s[i] = s[i+A.length]= A[i];
    9. }
    10. for(int i = 1 ; i < s.length;i++) {
    11. s[i] = s[i-1] + s[i];
    12. }
    13. Deque<Integer> q = new LinkedList<>();
    14. int len = A.length-1;
    15. for(int i = 0 ; i < s.length ; i++) {
    16. if(q.size()>0) {
    17. max = Math.max(s[i]-s[q.getFirst()],max);
    18. }
    19. if(q.size()>0 && i-len>q.getFirst()) q.pollFirst();
    20. while(q.size() >0 && s[q.getLast()]>=s[i]) q.pollLast();
    21. q.addLast(i);
    22. }
    23. return max;
    24. }
    25. }