【算法系列-栈与队列】队列的应用(前k高频元素 + 滑动窗口最大值)

【算法系列-栈与队列】队列的应用(前k高频元素 + 滑动窗口最大值)

文章目录

  • [【算法系列-栈与队列】队列的应用(前k高频元素 + 滑动窗口最大值)](#【算法系列-栈与队列】队列的应用(前k高频元素 + 滑动窗口最大值))
    • [1. 滑动窗口最大值(LeetCode 239)](#1. 滑动窗口最大值(LeetCode 239))
      • [1.1 思路分析🎯](#1.1 思路分析🎯)
      • [1.2 解题过程🎬](#1.2 解题过程🎬)
      • [1.3 代码示例🌰](#1.3 代码示例🌰)
    • [2. 前k个高频元素(LeetCode 347)](#2. 前k个高频元素(LeetCode 347))
      • [2.1 思路分析🎯](#2.1 思路分析🎯)
      • [2.2 代码示例🌰](#2.2 代码示例🌰)

1. 滑动窗口最大值(LeetCode 239)

【题目链接】239. 滑动窗口最大值 - 力扣(LeetCode)

1.1 思路分析🎯

这道题使用单调队列的方式解决

Dequeue(双端队列) + 自定义队列 -> 形成单调队列

这里我们维护一个队列:

队列出口处的数值保证是当前窗口下的最大值;

每次往队列添加元素,先将排在当前元素之前且比当前元素小的数都从队列中弹出,再将元素添加进队列中;

每次从队列弹出元素,得当元素等于队列出口元素时才可弹出,否则无需操作队列

1.2 解题过程🎬

初始化上述定义的队列,先将前k个元素添加到队列中,添加时队列会进行判断,最后留在出口位置的是当前窗口中的最大值;之后从 下标k 开始进行窗口移动,取队列出口值添加进返回数组;

直到nums数组遍历完,返回结果数组

1.3 代码示例🌰

java 复制代码
class Solution {

    class MyQueue {
        
        Deque<Integer> queue = new LinkedList<>();

        void poll(int val) {
            
            // 当元素等于队列出口元素时才可弹出,否则无需操作队列
            if (!queue.isEmpty() && queue.peek() == val) {
                queue.poll();   
            }
        }

        void add(int val) {
            // 每次往队列添加元素,先将排在当前元素之前且比当前元素小的数都从队列中弹出,再将元素添加进队列中
            while (!queue.isEmpty() && val > queue.getLast()) {
                queue.removeLast(); // 双端队列Dequeue可以从后弹出元素
            }
            queue.add(val);
        }

        // 队列出口处维护的就是最大值
        int peek() {
            return queue.peek();
        }
    }

    public int[] maxSlidingWindow(int[] nums, int k) {
        
        MyQueue queue = new MyQueue();
        int[] ret = new int[nums.length - k + 1];
        for (int i = 0;i < k;i++) {
            queue.add(nums[i]);
        }
        int len = 0;
        ret[len++] = queue.peek();
        // i = k,开始窗口移动
        for (int i = k;i < nums.length;i++) {
            queue.poll(nums[i - k]);
            queue.add(nums[i]);
            ret[len++] = queue.peek();
        }
        return ret;
    }
}

2. 前k个高频元素(LeetCode 347)

【题目链接】347. 前 K 个高频元素 - 力扣(LeetCode)

2.1 思路分析🎯

map映射 + 优先级队列

通过map来记录每个元素出现的频率,之后使用优先级队列 (这里使用小根堆,即父元素小于左右子元素,最小的元素在堆顶),通过遍历将每个map元素转换成数组并都添加进队列中,且当队列元素大于k时,将堆顶元素弹出(最小值),从而保证队列中只存在k个元素,最后弹出队列中的每个元素并取0下标值(原map的key),赋值给返回数组

2.2 代码示例🌰

java 复制代码
class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        Map<Integer, Integer> map = new HashMap<>();
        PriorityQueue<int[]> queue = new PriorityQueue<>((n1, n2) -> n1[1] - n2[1]);
        for (int x : nums) {
            map.put(x, map.getOrDefault(x, 0) + 1);
        }
        for (Map.Entry<Integer, Integer> entry : map.entrySet()) {

            int[] temp = new int[2];
            temp[0] = entry.getKey();
            temp[1] = entry.getValue();
            queue.offer(temp);
            if (queue.size() > k) {
                queue.poll();
            }
        }
        int[] ret = new int[k];
        for (int i = 0;i < k;i++) {
            ret[i] = queue.poll()[0];
        }
        return ret;
    }
}

以上便是对一些队列应用相关问题的介绍了!!后续还会继续分享其它算法系列内容,如果这些内容对大家有帮助的话请给一个三连关注吧💕( •̀ ω •́ )✧( •̀ ω •́ )✧✨

相关推荐
补三补四10 分钟前
SMOTE 算法详解:解决不平衡数据问题的有效工具
人工智能·算法
RTC老炮36 分钟前
webrtc弱网-RobustThroughputEstimator源码分析与算法原理
网络·算法·webrtc
听风吹等浪起1 小时前
分类算法-逻辑回归
人工智能·算法·机器学习
敲代码的嘎仔1 小时前
JavaWeb零基础学习Day2——JS & Vue
java·开发语言·前端·javascript·数据结构·学习·算法
yacolex1 小时前
3.3_数据结构和算法复习-栈
数据结构·算法
茉莉玫瑰花茶2 小时前
动态规划 - 两个数组的 dp 问题
算法·动态规划
微笑尅乐2 小时前
从暴力到滑动窗口全解析——力扣8. 字符串转换整数 (atoi)
算法·leetcode·职场和发展
火花怪怪2 小时前
LaMer结晶动力学模型
算法
legendary_bruce2 小时前
【22.2 增强决策树】
算法·决策树·机器学习
老马啸西风3 小时前
力扣 LC27. 移除元素 remove-element
算法·面试·github