LeetCode热题100——滑动窗口最大值(11)

文章介绍了两种方法来解决LeetCode上的滑动窗口最大值问题:一种是利用优先队列(大根堆)动态维护窗口内的最大值,另一种是使用单调队列(双端队列)保持窗口内的元素顺序。这两种数据结构有助于高效地找到每个窗口内的最大值。
摘要由CSDN通过智能技术生成

题目链接:https://leetcode.cn/problems/sliding-window-maximum/description/?envType=study-plan-v2&envId=top-100-liked

优先队列

大根堆存储每个窗口最大值,如果最大值不在窗口内,则弹出

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        int n = nums.length;
        //创建一个优先队列,大根堆,堆顶是队列最大值,比较函数第二个参数大
        PriorityQueue<int[]> pq = new PriorityQueue<int[]>(new Comparator<int[]>() {
            public int compare(int[] pair1, int[] pair2){
                return pair1[0] != pair2[0] ? pair2[0] - pair1[0] : pair2[1] - pair1[1];
            }
        });
        //队列存储首个窗口的数组元素和下标
        for(int i = 0; i < k; i++){
            pq.offer(new int[]{nums[i], i});
        }
        //存储答案
        int[] ans = new int[n - k + 1];
        //存储第一个窗口最大值
        ans[0] = pq.peek()[0];
        //遍历剩下的窗口
        for(int i = k; i < n; i++){
            //每次存储当前位置元素和下标
            pq.offer(new int[]{nums[i], i});
            //如果最大值不在窗口内,则弹出,可能有多个都不在窗口内
            while(pq.peek()[1] <= i - k){
                pq.poll();
            }
            //更新答案
            ans[i - k + 1] = pq.peek()[0];
        }
        return ans;
    }
}

单调队列

维护一个单调递减的双端队列,如果都在窗口内,且左边小于右边,那么左边的值不可能为最大值,直接弹出,如果队首出窗口了,还需要弹出,所以需要个双端队列

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        int n = nums.length;
        //定义一个双端队列,存储数组下标,队列从大到小排列
        Deque<Integer> deque = new LinkedList<Integer>();
        //存储第一个窗口
        for(int i = 0; i < k; i++){
            //如果当前元素大于队尾,则把队尾去掉
            while(!deque.isEmpty() && nums[i] > nums[deque.peekLast()]){
                deque.pollLast();
            }
            //从队尾插入
            deque.offerLast(i);
        }
        //存储答案
        int[] ans = new int[n - k + 1];
        //存储第一个窗口最大值
        ans[0] = nums[deque.peekFirst()];
        //遍历剩下的窗口
        for(int i = k; i < n; i++){
            while(!deque.isEmpty() && nums[i] > nums[deque.peekLast()]){
                deque.pollLast();
            }
            deque.offerLast(i);
            //当队首不在窗口内,则弹出
            while(deque.peekFirst() <= i - k){
                deque.pollFirst();
            }
            //更新答案
            ans[i - k + 1] = nums[deque.peekFirst()];
        }
        return ans;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值