栈(stack),它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。上面是百度百科给出栈的定义。个人认为其实不一定非得是表尾进行插入删除,也可以是表头进行插入删除。栈的特点先进先出。这里分享两道和栈有关的例题。在Java中ArrayDeque类中的pop()和push()就可以实现压栈和出栈操作,peek()方法可以查看当前栈顶元素。
有效的括号
给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
1.左括号必须用相同类型的右括号闭合。
2.左括号必须以正确的顺序闭合。
3.每个右括号都有一个对应的相同类型的左括号。
示例 1:
输入:s = “()”
输出:true
示例 2:
输入:s = “()[]{}”
输出:true
示例 3:
输入:s = “(]”
输出:false
class Solution {
public boolean isValid(String s) {
Deque<Character> stack = new ArrayDeque<>();
for(int i = 0;i < s.length();i++){
if(s.charAt(i) == '('){
stack.push(')');
}else if(s.charAt(i) == '{'){
stack.push('}');
}else if(s.charAt(i) == '['){
stack.push(']');
}else if(stack.isEmpty() || stack.peek() != s.charAt(i)){
return false;
}else{
stack.pop();
}
}
return stack.isEmpty();
}
}
基本思路就是每次遇到左括号(‘(’,‘[’,‘{’),将其对应的右括号(‘)’,‘]’,‘}’)压入栈中。当遇到右括号时,判断栈顶元素是否与当前括号一致,不一致返回false,一致则将栈顶右括号弹出,继续遍历下一个符号。
以"{(())}[]“为例子,说明上述代码执行的过程。首先遇到’{',将”}“压入栈中,此时栈中元素为[”}“],之后遇到’(',将”)“压入栈中,此时栈中元素为[”)“, “}”],之后遇到’(',将”)“压入栈中,此时栈中元素为[ “)”, “)”, “}”],之后遇到’)',栈顶元素为”)“,相等,将栈顶元素弹出,此时栈中元素为[”)“, “}”],之后遇到’)',栈顶元素为”)“,相等,将栈顶元素弹出,此时栈中元素为[”}“],之后遇到’}',栈顶元素为”}“,相等,将栈顶元素弹出,此时栈中元素为[],之后遇到’[',将”]“压入栈中,此时栈中元素为[”]“],之后遇到’]',栈顶元素为”]“,相等,将栈顶元素弹出,此时栈中元素为[]。while循环结束,返回stack.isEmpty(),栈为空,返回true。
最后为什么要返回stack.isEmpty()作为最终答案,而不是直接返回true。举一个例子就很好说明白,比如”{()()“这个例子,整个while循环过程中,左括号和右括号的样式都是匹配的,如果在while循环最后直接返回true,显然不符合答案预期,而while循环结束,最后stack中会剩下[”}“],说明”}"没有匹配的右括号,所以可以根据stack是否为空返回最终的正确答案。
最小栈
设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
实现 MinStack 类:
1.MinStack() 初始化堆栈对象。
2.void push(int val) 将元素val推入堆栈。
3.void pop() 删除堆栈顶部的元素。
4.int top() 获取堆栈顶部的元素。
5.int getMin() 获取堆栈中的最小元素。
class MinStack {
Deque<Integer> stack;
Deque<Integer> helper;
public MinStack() {
stack = new ArrayDeque<>();
helper = new ArrayDeque<>();
}
public void push(int val) {
stack.push(val);
if(helper.isEmpty() || helper.peek() > val){
helper.push(val);
}else{
helper.push(helper.peek());
}
}
public void pop() {
stack.pop();
helper.pop();
}
public int top() {
return stack.peek();
}
public int getMin() {
return helper.peek();
}
}
这题要求的栈和普通的栈的区别就是可以通过getMin方法得到栈中的最小元素。这里可以通过一个辅助栈来维护栈中的最小元素。
以[-2,-3,4,-1,-5]为例子,说明如何通过一个辅助栈维护栈中的最小元素。首先定义一个栈stack和辅助栈helper,并在MinStack类的构造方法中创建了两个栈的实例,之后来看push方法,关键就是push方法,首先压入-2,这个元素,stack直接压入-2,而helper辅助栈则需要判断栈是否为空,如果为空,直接压入,显然helper为空,直接将-2压入栈中。此时stack为[-2],helper[-2]。之后是-3,stack直接压入-3,而对于helper,此时已不为空,需要比较压入栈的元素-3和栈顶元素的大小,将更小的加入栈中,-3显然小于-2,则将-3压入栈中。此时stack为[-3, -2],helper[-3, -2]。之后是4,stack直接压入4,而helper需要比较栈顶元素和当前元素的大小4大于-3,继续将-3加入栈中。 此时stack为[4,-3, -2],helper[-3, -3, -2]。之后是-1,stack直接压入-1,而helper需要比较栈顶元素和当前元素的大小-1大于-3,继续将-3加入栈中。 此时stack为[-1, 4, -3, -2],helper[-3, -3, -3, -2]。之后是-5,stack直接压入-5,而helper需要比较栈顶元素和当前元素的大小-5小于-3,将-5加入栈中。 此时stack为[-5, -1, 4, -3, -2],helper[-5, -3, -3, -3, -2]。
显然如果需要获取栈中最小元素,直接返回helper栈顶元素即可。注意helper可以获取任意时刻栈的最小值,如压入-2后,栈中最小元素为-2,也是helper栈顶元素,压入4后,栈中最小元素为-3,也是helper栈顶元素,压入-5后,栈中最小元素为-5,也是helper栈顶元素。stack和helper的数量一定是相等,并一一对应的,对stack做出栈操作,也需要对helper做出栈操作。