本题出自LeetCode20:
给定一个只包括 ‘(’ , ‘)’ , ‘{’ , ‘}’ , ‘[’ , ‘]’ 的字符串s,判断字符串是否有效。有效字符串需满足:
示例:
输入:s = “()[]{}”
输出:true
本题比较麻烦的地方是如何判断两个符号是不是一组的,我们可以用哈希表将所有符号先存储,左半边做key,右半边做value。遍历字符串的时候,遇到左半边符号就入栈,遇到右半边符号就与栈顶的符号比较,不匹配就返回false。
代码实现如下:
boolean isValid(String s) {
if(s.length() <= 1) {
return false;
}
Map<Character, Character> smap = new HashMap<>();
smap.put('(', ')');
smap.put('[', ']');
smap.put('{', '}');
Stack<Character> stack = new Stack<>();
for(int i = 0; i < s.length(); i++){
char item = s.chatAt(i);
if (smap.containsKey(item)){
stack.push(item);
} else {
if (!stack.isEmpty()) {
Character left = stack.pop();
char rightchar = smap.get(left);
if (rightchat != item){
return false;
}
} else {
return false;
}
}
}
return stack.isEmpty();
}
本题出自LeetCode155. 设计一个支持push、pop、top操作,并能在常数时间内检索到最小元素的栈。
实现MinStack类:
示例:
本题可以借用另外一个栈,来存储栈内的最小值,如下图所示:
图中左侧的栈中存储栈内的实际值,右侧的Min栈中存储元素入栈时栈内的最小值。
因为题目要求在常数时间内获得栈中的最小值,因此不能在getMin()的时候再去计算最小值,最好应该再push或者pop的时候就计算好了当前栈中的最小值。
对于栈来说,如果一个元素a在入栈的时候,栈内有其他元素b,c,d,那么无论这个栈在之后经历什么操作,只要a在栈中,b,c,d就一定在栈中,因为在a被弹出之前,b,c,d不会被弹出。
因此,在操作过程中的任意一个时刻,只要栈顶的元素是a,那么我们就可以确定栈里面现在的元素一定是a,b,c,d。只要在每个元素a入栈之前把当前栈的最小值m存储起来。在这之后无论何时,如果栈顶的元素是a,就可以直接返回存储的最小值m。
因此可以只用一个辅助栈,与元素栈同步插入和删除,用于存储与每个元素对应的最小值,使得每个元素a与其相应的最小值m时刻保持一一对应。
具体的思路如下:
这样在任意时刻,栈内元素的最小值就存储在辅助栈的栈顶元素中。
具体的实现代码如下:
class MinStack {
Deque<Integer> xStack;
Deque<Integer> minStack;
public MinStack() {
xStack = new LinkedList<Integer>();
minStack = new LinkedList<Integer>();
minStack.push(Integer.MAX_VALUE);
}
public void push(int x) {
xStack.push(x);
minStack.push(Math.min(minStack.peek(), x));
}
public void pop() {
xStack.pop();
minStack.pop();
}
public int top() {
return xStack.peek();
}
public int getMin() {
return minStack.peek();
}
}
本题来自LeetCode 716. 设计一个最大栈数据结构,既支持栈操作,又支持查找栈中最大元素。
实现MaxStack类:
本题与最小栈刚好相反,处理的方法是一样的,这里只讲最后一种popMax方法。
对于popMax(),由于我们知道当前栈中最大的元素值,因此可以直接将两个栈同时出栈,并存储第一个栈出栈的所有制。当某个时刻,第一个栈的出栈元素等于当前栈中最大的元素值时,就找到了最大值。此时在将之前第一个栈出栈的所有元素重新入栈,并同步更新第二个栈,就完成了popMax()操作。
代码实现如下:
public int popMax() {
int max = peekMax();
Deque<Integer> buffer = new LinkedList<Integer>();
while(top() != max) {
buffer.push(pop());
}
//循环结束后,此时的栈顶元素就是栈内的最大元素,将其出栈
pop();
while(!buffer.isEmpty()) {
push(buffer.pop());
}
return max;
}
栈的使用并不复杂,在使用的过程中只用记住栈的特点——先进后出就可以了。