算法——栈和队列

栈概述

这里描述的是数据结构的栈,是物理栈结构的一个抽象数据类型。模仿了栈结构的特点,而做出一系列的动作。

物理中栈的本质 就是内存中的一个区域。他的特殊之处就在于,CPU从中存取数据的方式。就好像弹夹装子弹,就是先入后出,后入先出

对于堆栈而言,如果栈顶和栈底重合,那么表示栈里面没有数据。如果需要往栈里面存放数据那么栈顶指针就往上挪一挪,然后将要存储的数据存放在栈顶 的位置。这个动作就叫做压栈\入栈 。当需要从栈中取出数据的时候,就先将数据保存到寄存器当中,然后栈顶往下挪 ,这个动作就叫做弹栈\出栈。但是要注意,出栈了以后,数据还是在堆栈中,只是这个数据就被当成了垃圾。

应用

重点是在题目中应用栈的结构思想。做题时,多数使用数组直接模拟栈或直接用C++ STL中的stack

一般是应付左右匹配类的题

栈的结构思想:

  • 一边压栈的同时一边检测是否需要出栈,出栈永远是刚刚后进的数据(会连续出栈)
  • 误区:
    • 对于一组数据不是先一股脑全部压栈再出栈,而是一边压栈一边有选择地出栈

题目

洛谷P4387

验证栈序列

思路:用栈模拟

按入栈顺序入栈,如果栈顶元素与出栈序列的元素相同,就将其弹出。

首先将入栈序列的第i个元素压到"stack"中,(i,j分别是入栈序列和出栈序列的下标)

判断(注意用while判断,因为可能连续弹出)"stack"中的栈顶元素是否和出栈序列中的第i个元素一致(栈为空就不用判断了)如果一致则弹出栈顶元素,j++;如果不致则继续压入入栈序列中的第i+1个元素

继续判断栈顶元素是否和出栈序列中的第j个元素一致,直到到达入栈序列的末尾。

最后如果"stack"为空或指针j到达出栈序列的末尾就输出Yes,否则输出No

力扣735

小行星碰撞

思路:用栈模拟

以下情况不会发生碰撞,可把当前行星压入栈:

  1. 栈为空,不管当前行星是正是负(往左还是往右)都要压入栈
  2. 当前行星和栈顶行星同号说明同向移动不会碰撞;
  3. 当前行星往右移动,栈顶行星向左移动也不会碰撞

只有一种情况会发生碰撞,需要出栈当前行星往左,栈顶行星往右,做判断:

  1. 栈顶元素大于abs(当前元素),当前元素被撞毁;
  2. 栈顶元素等于abs(当前元素),栈顶弹出和当前元素抵消,
  3. 栈顶元素小于abs(当前元素),栈顶弹出,并与新栈顶继续完成上述判断

最终返回栈即可

单调栈概述

栈中的元素是严格单调递增 或者递减 的,也就是说:从底到栈顶,元素的值逐渐增大或者减小 。多用于求解元素的左右大小边界问题:

  1. 向左找第一个比自身大的数。
  2. 向左找第一个比自身小的数。
  3. 向右找第一个比自身大的数。
  4. 向右找第一个比自身小的数。

注意:对于给定的序列,第1,2点从序列的左边往右找;第3,4点从右往左找

操作(以底到顶递增为例):

  • 如果新的元素比栈顶元素大,就入栈
  • 如果新的元素比栈顶小,那就一直把栈内元素弹出来,直到栈顶比新元素小

元素间大小判断:(以底到顶递增为例):

  • 当栈中已有元素需要出栈时(遇见了比它小的新元素),说明后续这个新元素是需要出栈的元素向后找第一个比其小的元素
  • 当元素出栈后,新栈顶元素是出栈元素向前找第一个比其小的元素

题目

洛谷P5788

单调栈模板

思路:求每个数后第一个大于他的数。

底到顶 递减栈。

从后往前扫,对于每个元素:

  1. 弹出栈顶比它小的元素
  2. 此时栈顶就是答案(放到一个数组)
  3. 加入这个元素

输出答案数组。

力扣42

接雨水

思路:按行计算我们需要寻找一个元素的 右边最大元素以及左边最大元素,来计算雨水面积。

单调栈:底到顶 递减。

当枚举的将要入栈的元素大于栈顶时,说明出现了凹槽,计算该凹槽的蓄水量:例如:栈内元素:2,1,3要入栈,3比栈顶大,出现了凹槽。凹槽右边是将入栈的元素,左边是栈顶向下第一个大于栈顶的元素。

怎么计算蓄水量:

高*宽。宽是下标的差值高是下标对应的元素值,所以栈中存下标。所以:将要入栈的元素大于栈顶下标对应的元素时说明出现了凹槽。此时将栈顶记录下来之后,不断出栈,直到新的栈顶大于旧栈顶。记:新栈顶为ntop,旧栈顶为top,将入栈的下标为i,则:宽=i-top-1;高=min(hntop,hi)-htop

单调队列:

概念和单调栈类似。应用很少,多用于对一些算法的优化(动态规划等),除非去参加icpc,ccpc,不然基本接触不到,不再整述。

优先队列:

普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出的特征。基于堆(大顶堆/小顶堆)实现。

编程中多使用C++容器:
#include <queue>
priority_queue<int>pq;//大顶堆
priority_queue<int,vector<int>,greater<int> > p;//小顶堆

相关推荐
Navigator_Z19 分钟前
LeetCode //C - 1248. Count Number of Nice Subarrays
c语言·算法·leetcode
wzdark1 小时前
多维数组在算法设计中的存储映射问题4
算法
Phil3232 小时前
多智能体不是越多越好:Google《Towards a Science of Scaling Agent Systems》论文深度解读
算法
6Hzlia2 小时前
【Classic 150 刷题计划】 LeetCode 26. 删除有序数组中的重复项 | C++ 快慢双指针经典模板
c++·算法·leetcode
huang5791472 小时前
基于滑动窗口的流式数据算法优化思路3
算法
Ulyanov3 小时前
AudioVision Pro:基于 PySide6 + sounddevice 的实时音频可视化播放器设计
python·算法·音视频
土司大王3 小时前
LeetCode hot100——74.搜索二维矩阵:Java 二分模板
java·算法·leetcode
tyler_download3 小时前
揉扁搓圆transformer架构:NAG优化器算法详解
深度学习·算法·transformer
weixin199701080163 小时前
[特殊字符]《京东POP二手品类对接:B2C订单模型 vs 二手C2C属性的字段转换难题》(附Python源码)
前端·python·算法
Jared_devin4 小时前
单头、多头 Self-Attention可视化
人工智能·pytorch·深度学习·算法·机器学习·pycharm