2.白银挑战——栈的经典算法问题
括号匹配问题
链接:https://leetcode.cn/problems/valid-parentheses/
给定一个只包括 '('
,')'
,'{'
,'}'
,'['
,']'
的字符串 s
,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 每个右括号都有一个对应的相同类型的左括号。
示例 1:
输入:s = "()"
输出:true
示例 2:
输入:s = "()[]{}"
输出:true
示例 3:
输入:s = "(]"
输出: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.charAt(i);
if(smap.containsKey(item)){
stack.push(item);
}else{
if(!stack.isEmpty()){
Character left = stack.pop();
char rightchar = smap.get(left);
if(rightchar != item){
return false;
}
}else {
return false;
}
}
}
return stack.isEmpty();
}
思路:运用哈希表先将一对一对的字符串进行存储,分别作为 key 和 value,如果是 key 就放入栈中,如果是 value 就进行比较消除,消除失败则返回 false。这里主要的思想是将两种需要相抵的量用 key 和 value 分别加以存储。
最小栈
链接:https://leetcode.cn/problems/min-stack/
设计一个支持 push
,pop
,top
操作,并能在常数时间内检索到最小元素的栈。
实现 MinStack
类:
MinStack()
初始化堆栈对象。void push(int val)
将元素val推入堆栈。void pop()
删除堆栈顶部的元素。int top()
获取堆栈顶部的元素。int getMin()
获取堆栈中的最小元素。
示例 1:
输入:
["MinStack","push","push","push","getMin","pop","top","getMin"]
[[],[-2],[0],[-3],[],[],[],[]]
输出:
[null,null,null,null,-3,null,0,-2]
解释:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); --> 返回 -3.
minStack.pop();
minStack.top(); --> 返回 0.
minStack.getMin(); --> 返回 -2.
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();
}
}
思路:用另一个栈来存储最小值,把每次遍历到的最小值输入,那么他就会生成一个带有排序功能的队列(最小堆)。每次删除元素的时候我们只需要同时对于最小堆中的元素进行判断之后再进行删除即可。
最大栈
链接:https://leetcode.cn/problems/max-stack/
设计一个最大栈数据结构,既支持栈操作,又支持查找栈中最大元素。
实现 MaxStack
类:
MaxStack()
初始化栈对象void push(int x)
将元素 x 压入栈中。int pop()
移除栈顶元素并返回这个元素。int top()
返回栈顶元素,无需移除。int peekMax()
检索并返回栈中最大元素,无需移除。int popMax()
检索并返回栈中最大元素,并将其移除。如果有多个最大元素,只要移除 最靠近栈顶 的那个。
示例:
输入
["MaxStack", "push", "push", "push", "top", "popMax", "top", "peekMax", "pop", "top"]
[[], [5], [1], [5], [], [], [], [], [], []]
输出
[null, null, null, null, 5, 5, 1, 5, 1, 5]
解释
MaxStack stk = new MaxStack();
stk.push(5); // [5] - 5 既是栈顶元素,也是最大元素
stk.push(1); // [5, 1] - 栈顶元素是 1,最大元素是 5
stk.push(5); // [5, 1, 5] - 5 既是栈顶元素,也是最大元素
stk.top(); // 返回 5,[5, 1, 5] - 栈没有改变
stk.popMax(); // 返回 5,[5, 1] - 栈发生改变,栈顶元素不再是最大元素
stk.top(); // 返回 1,[5, 1] - 栈没有改变
stk.peekMax(); // 返回 5,[5, 1] - 栈没有改变
stk.pop(); // 返回 1,[5] - 此操作后,5 既是栈顶元素,也是最大元素
stk.top(); // 返回 5,[5] - 栈没有改变
class MaxStack {
Stack<Integer> stack;
Stack<Integer> maxStack;
public MaxStack() {
stack = new Stack();
maxStack = new Stack();
}
public void push(int x) {
int max = maxStack.isEmpty() ? x : maxStack.peek();
maxStack.push(max > x ? max : x);
stack.push(x);
}
public int pop() {
maxStack.pop();
return stack.pop();
}
public int top() {
return stack.peek();
}
public int peekMax() {
return maxStack.peek();
}
public int popMax() {
int max = peekMax();
Stack<Integer> buffer = new Stack();
while (top() != max) buffer.push(pop());
pop();
while (!buffer.isEmpty()) push(buffer.pop());
return max;
}
}