包括单调栈和优先队列
232. 用栈实现队列
用栈实现队列
两个栈
入队:向入队栈中加入元素
出队:从出队栈中出栈元素,如果出队栈为空,将入队栈所有元素入栈到出队栈。这样顺序就对了
225. 用队列实现栈
用队列实现栈
优化
其实这道题目就是用一个队列就够了。
一个队列在模拟栈弹出元素的时候只要将队列头部的元素(除了最后一个元素外) 重新添加到队列尾部,此时再去弹出元素就是栈的顺序了。
20.有效的括号
有效的括号
遍历字符串
如果是左括号,将对应右括号入栈,方便对比出栈
如果栈为空(左右括号数量不一致),或当前右括号与栈顶元素不匹配,返回false
遍历括号串结束,如果栈未空,也是左右括号数量不一致
1047.删除字符串中的所有相邻重复项
删除字符串中的所有相邻重复项
遍历字符串
如果栈不为空,且字符等于 栈顶字符(上一次加入的字符),说明该字符重复(连续出现2次)
不加入该字符,并且将与其重复的字符出栈,并删除
只用StringBuilder也可以直接模拟栈
sb.append(ch);
sb.deleteCharAt(sb.length() - 1);
155.最小栈
最小栈
两个栈做法
一个栈去保存正常的入栈出栈的值,另一个栈去存最小值,也就是用栈顶保存当前所有元素的最小值。
对于存最小值的栈:
新加入的元素如果大于栈顶元素,那么新加入的元素就不处理。
新加入的元素如果小于等于栈顶元素,那么就将新元素入栈。
出栈元素不等于栈顶元素,不操作。
出栈元素等于栈顶元素,那么就将栈顶元素出栈。
一个栈做法
只用一个变量去保存最小值
如果只用一个变量就会遇到一个问题,如果把 min
更新 了,那么之前的最小值 就丢失了。
怎么把 之前的最小值 保存起来呢?解决办法:把它在 新最小值
之前压入栈中即可。
150.逆波兰表达式
逆波兰表达式求值
逆波兰表达式:是一种后缀表达式,所谓后缀就是指运算符写在后面
平常使用的算式则是一种中缀表达式,如 ( 1 + 2 ) * ( 3 + 4 )
该算式的逆波兰表达式写法为 ( ( 1 2 + ) ( 3 4 + ) * )
用栈操作运算:
遇到数字则入栈;
遇到运算符则取出栈顶两个数字进行计算,并将结果压入栈中
394.字符串解码
394. 字符串解码
看到括号的匹配,首先应该想到的就是用栈来解决问题
括号内嵌套括号,需要从内向外生成与拼接字符串,这与栈的先入后出特性对应
单调栈
739.每日温度
每日温度
遍历温度数组:
- 从第二天开始,检查当前温度与栈顶索引对应的温度:
- 如果当前温度小于等于栈顶温度,说明需要继续等待,将当前索引压入栈。
- 如果当前温度大于栈顶温度,进入循环:
- 计算从栈顶索引到当前索引的天数差,并更新结果数组。
- 弹出栈顶索引,继续检查栈中的其他索引。
496. 下一个更大元素 I
下一个更大元素 I
遍历第二个数组,HashMap 记录 每个数字及其下一个更大数字(单调栈查找)的键值对
再遍历第一个数组 用 map 填充答案数组
503.下一个更大的元素 II
下一个更大元素 II
在循环数组中找下一个更大元素
思路:循环一次就知道下一个比他大的数,取余即可得到原来的索引
84. 柱状图中最大的矩形
柱状图中最大的矩形
由暴力两边开花做法想到单调栈做法
42. 接雨水
接雨水
优先队列
什么是优先级队列呢?
其实就是一个披着队列外衣的堆,因为优先级队列对外接口只是从队头取元素,从队尾添加元素,再无其他取元素的方式,看起来就是一个队列。
347.前K个高频元素
前 K 个高频元素
首先统计元素出现的频率,这一类的问题可以使用map来进行统计。
然后是对频率进行排序,使用容器优先级队列。
295.数据流的中位数
要想在 O(1) 的复杂度内取得当前中位数,可以把数据流分为左右两段
295. 数据流的中位数
左边一段是大顶堆
右边一段是小顶堆