单调栈介绍
单调栈的意思是维护一个单调递增或者单调递减的栈, 最通用的解法是找到右边第一个比它大的元素或者找到右边第一个比它小的元素。
单调队列介绍
单调队列也是一个维护递增或者递减顺序的队列,一般情况下比单调栈要复杂…适合处理比较复杂的操作,比如滑动窗问题…
通用思路
无论是单调栈还是单调队列,一般都是要O(n)时间复杂度处理"数组", 在while循环中进行单调栈或者单调队列的处理操作。
数据结构具体实现
由于在Java中的Stack性能很差,而且不够灵活,所以不推荐使用.
一般有两种替代方案:
ArrayDeque -----底层为数组
push()----压栈
pop() —出栈
peek() —取栈顶
pollLast() —取栈尾(这里其实有点像队列了…)
LinkedList ----底层为链表
上述两种实现都可以用来实现单调栈或者单调队列…
单调栈例题
- 移掉K位数字
class Solution {
public String removeKdigits(String num, int k) {
//单调栈
if (num == null || num.length() == 0) {
return "";
}
LinkedList<Character> stack = new LinkedList<>();
for (char c : num.toCharArray()) {
while (k > 0 && !stack.isEmpty() && c < stack.peek()) {
stack.pop();
k--;
}
//加入栈中, 去掉前导0
if (c != '0' || !stack.isEmpty()) {
stack.push(c);
}
}
while (k > 0 && !stack.isEmpty()) {
stack.pop();
k--;
}
StringBuilder res = new StringBuilder();
while (!stack.isEmpty()) {
res.append(stack.pollLast());
}
return res.length() == 0 ? "0" : res.toString();
}
}
84 柱状图中最大的矩形
class Solution {
public int largestRectangleArea(int[] heights) {
//维护广义递增(>=)单调栈
if (heights == null || heights.length == 0) {
return 0;
}
Deque<Integer> stack = new ArrayDeque<>();
//索引, 非常重要
int i = 0;
int area = 0;
int res = 0;
while (i < heights.length) {
if (stack.isEmpty() || heights[i] >= heights[stack.peekFirst()]) {
stack.offerFirst(i++);
} else {
//开始求出某个柱子的最大矩形
int top = heights[stack.pollFirst()];
if (stack.isEmpty()) {
area = top * i;
} else {
area = top * (i - stack.peekFirst() - 1);
}
}
res = Math.max(res, area);
}
//继续处理留在栈里的元素
while (!stack.isEmpty()) {
int top = heights[stack.pollFirst()];
if (stack.isEmpty()) {
area = top * i;
} else {
area = top * (i - stack.peekFirst() - 1);
}
res = Math.max(res, area);
}
return res;
}
}
单调队列例题
剑指 Offer 59 - I. 滑动窗口的最大值
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
//单调队列, 单调递减队列
if (nums == null || nums.length == 0) {
return new int[0];
}
Deque<Integer> que = new ArrayDeque<>();
int[] res = new int[nums.length - (k - 1)];
int index = 0;
for (int i = 0; i < nums.length; i++) {
while (!que.isEmpty() && que.peekFirst() < i - (k - 1)) {
que.pollFirst();
}
while (!que.isEmpty() && nums[que.peekLast()] < nums[i]) {
que.pollLast();
}
que.offerLast(i);
if (i >= k - 1) {
res[index++] = nums[que.peekFirst()];
}
}
return res;
}
}