1栈的原理
栈是一种线性表,仅在表尾进行插入和删除的线性表,称为栈顶。是按照先进后出的原则储存数据。
2栈的适用场景
- 维持最值属性:在遍历线性表时需要需要维持遍历过程中的最大\最小值
- 匹配后删除:入栈后等待匹配然后再退栈,实现局部动态匹配,达到全局的匹配
- 二叉树的遍历
- 图的深度优先算法
3例题分析
3.1有效的括号匹配
示例1:20.有效的括号
题目描述
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。
输入输出示例
示例 1:
输入: “()”
输出: true
示例 2:
输入: “()[]{}”
输出: true
示例 3:
输入: “(]”
输出: false
示例 4:
输入: “([)]”
输出: false
直观思想
先将括号对放置HashMap中,当遍历字符串时,当遇到左括号后我们期望在后续的遍历中能够遇到同类的右括号,所以先把左括号放入栈顶,当遍历到同类的括号时,出栈完成一次括号匹配。
代码实现
class Solution {
private HashMap<Character, Character> mappings;
public Solution(){
this.mappings = new HashMap<Character, Character>();
this.mappings.put(')', '(');
this.mappings.put(']', '[');
this.mappings.put('}', '{');
}
public boolean isValid(String s) {
Stack<Character> stack = new Stack<>();
for (int i = 0; i < s.length(); i++){
char c = s.charAt(i);
if (this.mappings.containsKey(c)){
char topElement = stack.empty() ? '#' : stack.pop();
char ch = this.mappings.get(c);
if (topElement != ch){
return false;
}
}
else{
stack.push(c);
}
}
return stack.isEmpty();
}
}
3.2接雨水问题
示例2:42.接雨水
题目描述
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。
输入输出描述
输入: [0,1,0,2,1,0,1,3,2,1,2,1]
输出: 6
直观思想
遍历数组时维护一个栈,如果当前的条形块小于或等于栈顶的条形块,我们将条形块的索引入栈,意思是当前的条形块被栈中的前一个条形块界定。如果我们发现一个条形块长于栈顶,我们可以确定栈顶的条形块被当前条形块和栈的前一个条形块界定,因此我们可以弹出栈顶元素并且累加答案到ans 。
算法流程:
- 使用栈来储存数组的索引下标
- 遍历数组:
\quad 当栈非空且 height [ c u r r e n t ] > height [ s t . t o p ( ) ] \text{height}[current]>\text{height}[st.top()] height[current]>height[st.top()]
\qquad 意味着栈中元素可以被弹出。弹出栈顶元素 t o p top top。
\qquad 计算当前元素和栈顶元素的距离,准备进行填充操作
d i s t a n c e = c u r r e n t − s t . t o p ( ) − 1 \qquad distance=current−st.top()−1 distance=current−st.top()−1
b o u n d e d h e i g h t = m i n ( h e i g h t [ c u r r e n t ] , h e i g h t [ s t . t o p ( ) ] ) − h e i g h t [ t o p ] \qquad bounded_height=min(height[current],height[st.top()])−height[top] boundedheight=min(height[current],height[st.top()])−height[top]找出界定高度
\qquad 往结果中添加积水量, a n s + = d i s t a n c e × b o u n d e H e i g h t ans+=distance \times boundeHeight ans+=distance×boundeHeight
\qquad
将当前索引下标入栈
\qquad
将
c
u
r
r
e
n
t
将current
将current移动到下一个位置
代码实现
public int trap(int[] height) {
int ans = 0, current = 0;
Stack<Integer> stack = new Stack<>();
while (current < height.length) {
while (!stack.isEmpty() && height[current] > height[stack.peek()]) {
int top = stack.pop();
if (stack.isEmpty()) break;
int distance = current - stack.peek() - 1;
int boundedHeight = Math.min(height[current], height[stack.peek()]) - height[top];
ans += distance * boundedHeight;
}
stack.push(current++);
}
return ans;
}
4栈的常用方法
E push(E item)
将item压入栈顶synchronized E peek()
获得栈顶元素synchronized E pop()
移出栈顶对象,并且将该对象作为返回值synchronized boolean isEmpty()
判断该栈是否为空boolean contains(Object o)
该栈是否包含对象synchronized E firstElement()
返回栈底元素synchronized E lastElement()
返回栈顶元素
题型总结目录
题型总结——前K系列(堆、优先队列).
题型总结——二分查找(中间点计算的改进).
题型总结——二维数组(矩阵)之逆逆时针输出、查找.
题型总结——栈的应用.
题型总结——双指针算法全部模型(持续更新).