一、单调栈
1.单调栈中存放的数据是有序的
单调递增栈:从栈顶到栈底单调第增;
单调递减栈:从栈顶到栈底单调第减。
2.声明单调栈
Deque<E> stack = new ArrayDeque<>();
Deque是Queue的子接口,我们知道Queue是一种队列形式,而Deque则是双向队列,它支持从两个端点方向检索和插入元素,因此Deque既可以支持LIFO形式也可以支持LIFO形式.Deque接口是一种比Stack和Vector更为丰富的抽象数据形式,因为它同时实现了以上两者.
常用方法:
插入元素
1.push(E),向队列头部插入元素
2.addFirst(E),向队列头部插入元素
3.addFirst(E),向队列尾部插入元素
获取元素
4.peekFirst(),获取队列头部元素
5.peekLast(),获取队列尾部元素
弹出元素
6.pop(),弹出队列头部元素
7.removeFirst(),弹出队列头部元素
8.removeLast(),弹出队列尾部元素
3.如何实现单调栈
实现单调递减栈(栈为空或者栈顶元素比入栈元素小时才可入栈):设有一组数据2,1,5,6,2,3,从左往右依次入栈:
1)2入栈时,栈为空,可直接入栈;
2)1准备入栈,由于栈顶元素2大于1,所以2出栈,1入栈;
3)5准备入栈,由于栈顶元素1小于5,则5入栈,此时栈内元素有1,5;
4)6准备入栈,5<6,则6入栈,此时栈内元素有1,5,6;
5)2准备入栈,6>2,则6出栈;5>2,则5也出栈;1<2,则2入栈;
6)3准备入栈,2<3,则3入栈,此时栈内元素有1,2,3,栈顶为3,栈底为1。
伪代码(Java)
//设待入栈的数组为nums
Deque<Integer> st = new ArrayDeque<>();//定义一个栈,实质为双边队列,从尾部入栈,出栈的时候程序从顶部取元素出栈
int len = 数组长度;
int index = 0;
while(index<len){
while(index<len && (栈空||栈顶元素小于等于等待入栈元素)){
st.addLast(nums[index++]);//入栈;
}
if(index = len)
break;
while(栈非空 && 栈顶元素大于等待入栈元素 && st.size()+len-index-1>=最后要保留的数组长度){
st.removeLast();//栈顶元素出栈;
}
st.addLast(nums[index++]);//等待入栈元素入栈;
}
//从栈顶取排好序的元素出来
用st.pollFirst();或st.removeFirst();
}
二、例题讲解
LeetCode 402题
解题思路:
1.先考虑用单调增还是单调减栈
这里要求移除k个元素后得到的最终结果值最小,则左边的数肯定是越小越好,所以用单调递增栈,保证最后结果开头数字最小;
2.注意什么时候停止,由于最后要保留num.length-k个数字,所以要确保有足够的数。
class Solution {
public String removeKdigits(String num, int k) {
Deque<Character> st = new ArrayDeque<>();
int index = 0;
int len = num.length();
int count = len-k;
if(count==0) return "0";
while(index < len){
while(index<len&&(st.isEmpty()||st.peekLast()<=num.charAt(index))){
st.addLast(num.charAt(index++));
}
if(index==len)
break;
while(!st.isEmpty() && st.peekLast()>num.charAt(index) && st.size()+len-index-1 >= count){
st.removeLast();
}
st.addLast(num.charAt(index++));
}
StringBuilder sb = new StringBuilder();
while(!st.isEmpty() && st.peekFirst()=='0')
st.removeFirst();
if(st.isEmpty())
return "0";
index = 0;
while(!st.isEmpty()&&index < count){//只取st的前count个数
sb.append(st.removeFirst());
index++;
}
return sb.toString();
}
}
单调栈的例题在LeetCode上还有316、321、42、84等