当前位置: 首页 > news >正文

算法打卡 Day13(栈与队列)-滑动窗口最大值 + 前 K 个高频元素 + 总结

文章目录

  • Leetcode 239-滑动窗口最大值
    • 题目描述
    • 解题思路
  • Leetcode 347-前 K 个高频元素
    • 题目描述
    • 解题思路
  • 栈与队列总结

Leetcode 239-滑动窗口最大值

题目描述

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

在这里插入图片描述

解题思路

在本题中我们使用自定义的单调队列来实现:

pop:如果窗口移除的元素 value 等于单调队列的出口元素,那么队列弹出元素,否则不进行任何操作

push:如果 push 的元素 value 大于入口元素的数值,那么就将队列入口的元素弹出,直到 push 元素的数值小于队列入口元素的数值为止

返回当前窗口的最大值:调用 que.front()

class Solution {
private:class MyQueue {public:deque<int> que; //使用deque实现单调队列void pop(int value) {if (!que.empty() && value == que.front()) {que.pop_front();}}void push(int value) {while (!que.empty() && value > que.back()) {que.pop_back();}que.push_back(value);}int front() {return que.front();}};
public:vector<int> maxSlidingWindow(vector<int>& nums, int k) {MyQueue que;vector<int> result;for (int i = 0; i < k; i++) {que.push(nums[i]);}result.push_back(que.front());for (int i = k; i < nums.size(); i++) {que.pop(nums[i - k]);que.push(nums[i]);result.push_back(que.front());}return result;}
};

Leetcode 347-前 K 个高频元素

题目描述

https://leetcode.cn/problems/top-k-frequent-elements/description/

在这里插入图片描述

解题思路

这道题目需要解决三个部分的问题:

1. 统计元素的出现频率:
我们可以使用 unordered_map 来解决,其中 key 表示元素的值,value 表示值出现的次数
2. 对频率进行排序:
使用优先级队列,其是一个披着队列外衣的堆。优先级队列对外接口是从队头取元素,从队尾添加元素,其内部的元素自动依照元素的权值排列。优先级队列缺省情况下 priority_queue 利用 max-heap 大顶堆完成对元素的排列,大顶堆是以 vector 为表现形式的完全二叉树。

堆是完全二叉树,树中的每个结点都不小于(或不大于)其左右孩子的值。父亲结点大于等于左右孩子的是大顶堆,小于等于左右孩子的是小顶堆。

选用优先级队列而不是快排:我们只需要报告前 K 个高频元素而不是全部元素,因此只需要维护 K 个有序序列即可,当 n 非常大时,这样的方法可以降低时间复杂度。

使用小顶堆而不是大顶堆:因为要统计最大前 K 个元素,如果选用大顶堆会将最大的元素弹出不符合要求,而使用小顶堆可以每次将最小的元素弹出,最后小顶堆中积累的才是前 K 个最大元素。

3. 找出前 K 个高频元素

class Solution {
public://小顶堆class mycomparison{public:bool operator()(const pair<int, int>& lhs, const pair<int, int>& rhs) {return lhs.second > rhs.second;}};vector<int> topKFrequent(vector<int>& nums, int k) {//统计元素出现的频率unordered_map<int, int>map;for (int i = 0; i < nums.size(); i++) {map[nums[i]]++;}//根据频率进行排序//定义一个小顶堆,大小为kpriority_queue<pair<int, int>, vector<pair<int, int>>, mycomparison> pri_que;//用固定大小为k的小顶堆,扫描所有频率的数值for (unordered_map<int, int>::iterator it = map.begin(); it != map.end(); it++) {pri_que.push(*it);if (pri_que.size() > k) {//如果堆的大小大于k,则从队列弹出pri_que.pop();}}//找出前k个高频元素,小顶堆先弹出最小的,所以使用倒序输出数组vector<int> result(k);for (int i = k - 1; i >= 0; i--) {result[i] = pri_que.top().first;pri_que.pop();}return result;}};

栈与队列总结

栈和队列是容器适配器,底层容器使用不同的容器,那么栈内数据在内存中的分布就不一定连续。
在缺省状况下,栈和队列的默认底层容器时 deque,其内存分布不连续。

递归的实现是栈:每一次递归调用都会把函数的局部变量、参数值和返回地址等压入调用栈中,然后递归返回的时候,从栈顶弹出上一次递归的各项参数,所以这就是递归为什么可以返回上一层位置的原因。

相关文章:

  • 页面导出PDF,非可视区域如何解决
  • FL Studio v21.2.3.4004中文破解版百度网盘下载
  • 进程与线程学习
  • 回文链表(快慢指针解法之在推进过程中反转)
  • 《当微服务遇上Ribbon:一场负载均衡的华丽舞会》
  • Android Studio 所有历史版本下载
  • P1160 队列安排
  • Excel插入多行VBA实现
  • 【Real】[Flask]SSTI
  • 2024年,企业人才招聘怎么做?
  • B站pink老师HTML5基础(一)
  • SAP OBYC自动记账 详解
  • LangChain笔记
  • makefile一些特殊且常用的符号
  • 哈希算法教程(个人总结版)
  • [笔记] php常见简单功能及函数
  • 《Javascript数据结构和算法》笔记-「字典和散列表」
  • Android 初级面试者拾遗(前台界面篇)之 Activity 和 Fragment
  • exif信息对照
  • github从入门到放弃(1)
  • HashMap剖析之内部结构
  • iOS筛选菜单、分段选择器、导航栏、悬浮窗、转场动画、启动视频等源码
  • JavaScript-Array类型
  • JavaWeb(学习笔记二)
  • java第三方包学习之lombok
  • java取消线程实例
  • JDK 6和JDK 7中的substring()方法
  • Linux各目录及每个目录的详细介绍
  • MySQL QA
  • Sass Day-01
  • weex踩坑之旅第一弹 ~ 搭建具有入口文件的weex脚手架
  • XML已死 ?
  • 类orAPI - 收藏集 - 掘金
  • 前端性能优化--懒加载和预加载
  • 浅谈Kotlin实战篇之自定义View图片圆角简单应用(一)
  • 使用API自动生成工具优化前端工作流
  • 写给高年级小学生看的《Bash 指南》
  • 原生JS动态加载JS、CSS文件及代码脚本
  • 源码之下无秘密 ── 做最好的 Netty 源码分析教程
  • 阿里云ACE认证学习知识点梳理
  • 教程:使用iPhone相机和openCV来完成3D重建(第一部分) ...
  • ​​​​​​​GitLab 之 GitLab-Runner 安装,配置与问题汇总
  • ​MPV,汽车产品里一个特殊品类的进化过程
  • ​如何使用QGIS制作三维建筑
  • ​学习一下,什么是预包装食品?​
  • (7)STL算法之交换赋值
  • (k8s)kubernetes 部署Promehteus学习之路
  • (PHP)设置修改 Apache 文件根目录 (Document Root)(转帖)
  • (笔记自用)LeetCode:快乐数
  • (补充):java各种进制、原码、反码、补码和文本、图像、音频在计算机中的存储方式
  • (二)换源+apt-get基础配置+搜狗拼音
  • (个人笔记质量不佳)SQL 左连接、右连接、内连接的区别
  • (十八)SpringBoot之发送QQ邮件
  • (十六)Flask之蓝图
  • (一)【Jmeter】JDK及Jmeter的安装部署及简单配置