栈与队列的特点
1、栈:FIFO
栈是仅能对其一端进行操作的结构,实现后进先出的效果。在C++中采用容器适配器的方式实现栈。(容器适配器实际上就是对某一类型的对象进行泛化,定义了这一类泛化对象的可进行操作的逻辑)
什么是适配器,C++ STL容器适配器详解
stack的容器有三种有 vector、deque 和 list,默认使用的是deque容器。
2、队列:LIFO
队列是能对两端进行操作的结构,实现先进先出的效果。和 stack 栈容器适配器不同,queue 容器适配器有 2 个开口,其中一个开口专门用来输入数据,另一个专门用来输出数据,如图 1 所示。
这种存储结构最大的特点是,最先进入 queue 的元素,也可以最先从 queue 中出来,即用此容器适配器存储数据具有“先进先出(简称 “FIFO” )”的特点,因此 queue 又称为队列适配器。
C++ STL queue容器适配器详解
queue的容器有三种有 vector、deque 和 list,默认使用的是deque容器。
参考文章:栈与队列基础
栈相关题型
栈适用于对相邻元素进行某种判定和操作
(1)栈常规题
题目:
-
进栈匹配结果,可简化代码
83、【栈与队列】leetcode ——20. 有效的括号(C++版本) -
用栈适于对相邻元素进行操作的特点,对相邻元素进行判定,不重复元素入栈,重复元素弹出
84、【栈与队列】leetcode ——1047. 删除字符串中的所有相邻重复项:栈+双指针解法(C++版本) -
后缀表达式进入栈的过程,相当于对中缀形式的树进行后序遍历
85、【栈与队列】leetcode ——150. 逆波兰表达式求值(C++版本) -
双栈+运算符优先级操作,每次入栈前,先让栈中高优先级的运算符操作
193、【栈与队列】leetcode ——面试题 16.26. 计算器(C++版本)
(2)单调栈
单调栈常用于解决找到某一元素左边或右边第一个比它大或比它小的数。
模板
1)一个栈
for(int i = 1; i < n; i++) {
// 对于满足弹栈条件的,进行目标操作,进行循环弹出
while(!st.empty() && nums[st.top()] (><=) nums[i]) {
// Operation
st.pop();
}
// 此时满足入栈条件,可直接入栈
st.push(i);
}
2)两个主副栈
stack<int> s1, s2; // s1为主栈用来得到按规定顺序排列的元素,s2为副栈用来暂存s1中元素
while(!s1.empty() && s1.top() ><= val) {
s2.push(s1.top()); // 用s2来暂存s1中元素
s1.pop();
}
s1.push(val); // 按规定顺序排放val,将其放入s1中
while(!s2.empty()) {
s1.push(s2.top());
s2.pop();
}
-
维护一个单调递减栈
面试题 03.05. 栈排序:双栈实现单调栈(C++/Python版本):使用双栈实现,一个作为主栈,一个作为辅助栈 -
栈内存放元素为数组下标,存放顺序为自栈底到栈顶为单调递减。
184、【栈与队列】leetcode ——739. 每日温度(C++版本) -
存放方式与1相同,区别在于只有判定到两个数组中相等元素时,才记录结果。
185、【栈与队列】leetcode ——496. 下一个更大元素 I:单调栈-哈希表(C++版本) -
核心思路与1中相同,区别在于需要完成一个逻辑上为循环数组的遍历。
186、【栈与队列】leetcode ——503. 下一个更大元素 II(C++版本):思路一:增加元素;思路二:二次遍历 -
构建单调栈存储单调不增元素,遇到比栈顶大的元素弹栈,与左右比较找出最小高度,作差再乘上长度。
187、【栈与队列】leetcode ——42. 接雨水(C++版本) -
整体思路与上述相同,区别在于要维护的是一个自栈底到栈顶单调不减栈,遇到当前元素大于栈顶元素时弹出。
188、【栈与队列】leetcode ——84. 柱状图中最大的矩形(C++版本) -
84题的扩展题,首先计算出到达每个一元素其之前和当前连续1的个数,仅保留这些矩阵,此时就得到类似于直方图的各个小矩阵,再用84题中同样的解法,找到各个直方图中的最大面积。
203、【栈与队列】leetcode ——剑指 Offer II 040. 矩阵中最大的矩形 / 85. 最大矩形:暴力+单调栈(C++/Pyhont版本)
队列相关题型
(1)单调队列:维护一个单调不增或单调不减的队列。
(2)优先队列:按照大根堆或小根堆的排列方式,维护一个单调不减或单调不增的队列。(注意创建方式和排序对比函数)C++ STL priority_queue容器适配器详解
-
使用单调队列保证队首元素为最大值,每次移动滑动窗口也把移除元素从队列中弹出。
√ 86、【栈与队列】leetcode ——39. 滑动窗口最大值:单调队列+滑动窗口(C++版本) -
构建一个优先队列,用小根堆来维护里面k个元素,当有更大元素加入时,将最小元素弹出。
√ 87、【栈与队列】leetcode ——347. 前 K 个高频元素:优先队列(小根堆)+Hash表(C++版本)