leetcode 239. 滑动窗口最大值

114 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情

前言

继续学习栈与队列的相关知识,并进行刷题。今天刷了一道困难题,确实难度要高很多,在这发表一下我对这道题的理解。

题目

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

示例

image.png

初始思路

这道题最明显的解题办法就是暴力解决,但是暴力解决的复杂度十分高。像滑动窗口这种先入先出的结构就是明显的队列的结构。

我们会想到使用队列在队列里排序然后返回队列里最大的值,但是排序后的队列并不能像从前一样保持出队列的顺序。由此,我们需要一个队列可以push入元素,可以pop出元素,也可以返回我们一段内的最大值。

解题方法

pop(value):如果窗口pop出的元素等于单调队列的出口元素,队列弹出元素。否则不进行弹出。

push(value):如果push的元素大于入口元素的数值,那么就将队列入口的元素弹出,直到push元素的数值小于等于队列入口元素的数值为止。

front:返回队首元素。

代码

var maxSlidingWindow = function (nums, k) {
  class MonoQueue {
    queue;
    constructor() {
      this.queue = [];
    }
    enqueue(value) {
      let back = this.queue[this.queue.length - 1];
      while (back !== undefined && back < value) {
        this.queue.pop();
        back = this.queue[this.queue.length - 1];
      }
      this.queue.push(value);
    }
    dequeue(value) {
      let front = this.front();
      if (front === value) {
        this.queue.shift();
      }
    }
    front() {
      return this.queue[0];
    }
  }
  let helperQueue = new MonoQueue();
  let i = 0,
    j = 0;
  let resArr = [];
  while (j < k) {
    helperQueue.enqueue(nums[j++]);
  }
  resArr.push(helperQueue.front());
  while (j < nums.length) {
    helperQueue.enqueue(nums[j]);
    helperQueue.dequeue(nums[i]);
    resArr.push(helperQueue.front());
    i++, j++;
  }
  return resArr;
};

后记

今天这道题对我目前来说已经吃力,希望二刷的时候可以从容不迫。