Douc1998 / My_Leetcode

Leetcode_题解
0 stars 0 forks source link

剑指Offer 59 - I. 滑动窗口的最大值 #142

Open Douc1998 opened 1 year ago

Douc1998 commented 1 year ago

题目

给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值。

示例

输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
输出: [3,3,5,5,6,7] 
解释: 

  滑动窗口的位置                最大值
---------------               -----
[1  3  -1] -3  5  3  6  7       3
 1 [3  -1  -3] 5  3  6  7       3
 1  3 [-1  -3  5] 3  6  7       5
 1  3  -1 [-3  5  3] 6  7       5
 1  3  -1  -3 [5  3  6] 7       6
 1  3  -1  -3  5 [3  6  7]      7

考点:通过优先队列维护最值,保证最大值一直在队列头部,如果要插入一个值,队列中比它小的值都需要剔除掉,再插入。如果滑动窗口移动到最大值离开了窗口,就需要把队列头部的最大值给弹出。

function maxSlidingWindow(nums: number[], k: number): number[] {
    let priorityQueue: number[] = [];
    let len: number = nums.length;
    // 判断特殊情况
    if(len < k) return [];

    let res: number[] = [];
    for(let i = 0; i < len; i++){

        // 只有从 i >= k - 1 的时候开始才需要考虑可能要有值需要出队
        if(i >= k - 1){
            if(nums[i - k] === priorityQueue[0]){
                priorityQueue.shift();
            }
        }

        let queueLen: number = priorityQueue.length;
        // 如果不是第一个数,循环判断队列前面的值是否比 nums[i]小,如果小则要剔除
        while(queueLen > 0 && nums[i] > priorityQueue[queueLen - 1]){
            priorityQueue.pop();
            queueLen = priorityQueue.length;
        }
        // 把 nums[i] 插入队列尾部
        priorityQueue.push(nums[i]);

        // 只有到 i === k - 1 的时候,才开始取。优先级队列中头部一定是最大的
        if(i >= k - 1){
            res.push(priorityQueue[0])
        }
    }

    return res;
};