【算法系列-栈与队列】队列的应用(前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;
    }
}

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

相关推荐
不爱吃糖的程序媛几秒前
基于Ascend C开发的Vector算子模板库-ATVOSS 技术深度解读
人工智能·算法·机器学习
松涛和鸣1 分钟前
35、Linux IPC进阶:信号与System V共享内存
linux·运维·服务器·数据库·算法·list
Cx330❀6 分钟前
《C++ 动态规划》第001-002题:第N个泰波拉契数,三步问题
开发语言·c++·算法·动态规划
LYFlied7 分钟前
【每日算法】LeetCode 114. 二叉树展开为链表:从树结构到线性结构的优雅转换
数据结构·算法·leetcode·链表·面试·职场和发展
毕设源码-钟学长12 分钟前
【开题答辩全过程】以 基于Spark机器学习算法的体育新闻智能分类系统设计与实现为例,包含答辩的问题和答案
算法·机器学习·spark
天勤量化大唯粉14 分钟前
基于距离的配对交易策略:捕捉价差异常偏离的均值回归机会(天勤量化代码实现)
android·开发语言·python·算法·kotlin·开源软件·策略模式
智航GIS15 分钟前
ArcGIS大师之路500技---036通俗易懂讲解克里金法
人工智能·算法·arcgis
拼好饭和她皆失17 分钟前
逆元,除法同余原理
算法·逆元·除法同余原理
leiming619 分钟前
c++ 利用模板创建一个可以储存任意类型数据的数组类
开发语言·c++·算法
TL滕21 分钟前
从0开始学算法——第二十天(简易搜索引擎)
笔记·学习·算法