滑动窗口最大值——程序员的真实写照

发布于:2024-05-22 ⋅ 阅读:(45) ⋅ 点赞:(0)

LeetCode:https://leetcode.cn/problems/sliding-window-maximum/description/


一、一个故事

有一家互联网公司,它每个月都要招一名新的Java开发工程师。但是每一名工程师最多工作10个月就会被裁掉,无论他的工作能力多么好。

当这家公司招够了10个人之后,就开始对他们进行评估比较了,根据工程师的水平,选出这里面最好的一名,作为EOM(Employee of the Month),获得额外的薪水。之后的每个月,都有一位新人加入,一位老人固定被“优化”。

如果一个新人的能力比公司现在的老人能力还强,那在接下来的评比中,这些老人永远不会是Top1,他们的结局在这个新人进来的一刻就被注定了——他们既不可能作为EOM获得暂时的高工资,也难逃被裁的命运。所以每当有一名能力出众的新人入职,能力不如他的老人们都会集体辞职。

那么,每个月的EOM是谁呢?

这个问题,就是“滑动窗口最大值”,也称“谁是每月卷王?”。


二、关键点

请记住:

1、你注定被优化【不在窗口里了,就一定要移出队列】

2、如果一个人比你年轻还比你强,那你就失去了存在的意义【新来的比队列中的还大,那么队列中的就没有存在的必要了】

3、EOM,是干掉了他之前的所有人【最大的一定在队列的出口处】


三、实现代码

使用双端队列,实现单调队列

package StackAndQueue;

// 34 https://leetcode.cn/problems/sliding-window-maximum/description/

import java.util.Deque;
import java.util.LinkedList;

public class MaximumSlidingWindowValue {
    public int[] maxSlidingWindow(int[] nums, int k) {
        int[] result = new int[nums.length - k + 1];
        int resultIndex = 0;
        Deque<Integer> deque = new LinkedList<Integer>();

        for (int i = 0; i < nums.length; i++) {
            // 队首元素不在窗口内了,一定要把它移除
            if (!deque.isEmpty() && i - deque.peekFirst() >= k) {
                deque.removeFirst();
            }
            // 每进队一个元素,就把它前面的比他小的元素都移除
            while (!deque.isEmpty() && nums[deque.peekLast()] < nums[i]) {
                deque.removeLast();
            }
            deque.addLast(i);

            if (!deque.isEmpty() && i >= k - 1) {
                result[resultIndex++] = nums[deque.peekFirst()];
            }
        }

        return result;
    }
}