升华抽象:通过一个双向队列保存迭代过的所有可能是答案的元素,通过一些优先级,贡献,从队列中淘汰掉一些不可能是最终结果的点。
大堆小堆,也是维护所有已经迭代过的元素,只是大堆小堆不考虑元素的顺序,也就是在位置上的先后关系。
动作:新元素与队首队尾比较,刷新队列,刷新答案。
1.单调栈问题一般是一维数组
2.按照某种迭代顺序,把所有迭代到的元素推入栈中。
3.按照某种迭代顺序,元素的结果只和前面的元素有关。
4.按照某种迭代顺序,靠后元素满足某种条件时候优先级会高于前面的元素
也就是如果靠后的这个元素优于靠前的元素,前面的元素就再也不纳入考虑范围,那么可以把前面所有
更劣的元素推出栈。
5.最终栈会呈现出与条件相反的趋势,比如说更大的元素更优,那么栈就是单调递减的。反之亦然。
6.关注元素出栈的时候和入栈的时候
7.维护栈的单调递增,那么栈元素在出来的时候就是遇到比自己小的元素。
作用:使用单调栈可以找到元素向左遍历第一个比他小的元素,也可以找到元素向左遍历第一个比他大的元素
相关leetcode练习题汇总:
- 柱状图中最大的矩形(https://leetcode-cn.com/problems/largest-rectangle-in-histogram/)
- 每日温度 (https://leetcode-cn.com/problems/daily-temperatures/)
- 下一个更大元素 II (https://leetcode-cn.com/problems/next-greater-element-ii/)
- 最大矩形 (https://leetcode-cn.com/problems/maximal-rectangle/)
- 接雨水 (https://leetcode-cn.com/problems/trapping-rain-water/)
- 股票价格跨度 (https://leetcode-cn.com/problems/online-stock-span/)
- 滑动窗口最大值 (https://leetcode-cn.com/problems/sliding-window-maximum/)
- 最大宽度坡 (https://leetcode-cn.com/problems/maximum-width-ramp/)
- 移掉K位数字 (https://leetcode-cn.com/problems/remove-k-digits/)
每日温度:单调栈的简单应用,求元素的下一个更大元素
下一个更大元素 II :数组形式扩展,变为环状数组,将组拼接,假设原来的数组是A,则处理AA‘,A’ = A,A’中的每个元素实际上会对
排在自己前面的元素做一次重复,但是不影响结果。
参考代码:
public int[] nextGreaterElements(int[] nums) {
int[] res = new int[nums.length];
//配置好初始值,找不到更大的元素就默认-1,小技巧哦
Arrays.fill(res, -1);
Stack<Integer> stack = new Stack<>();
for (int i = 0; i < 2 * nums.length; i++) {
while (!stack.empty() && nums[stack.peek()] < nums[i % nums.length]) {
res[stack.pop()] = nums[i % nums.length];
}
stack.push(i % nums.length);
}
return res;
}
接雨水问题,官方共给出四种解法,分别是暴力,动态规划,单调递减栈,双指针。
暴力法没有用到每个点之间的关系,复杂度高。动态规划存储好每个点用到的左右界,但界还是有规律的。
双指针的写法:
public int trap(int[] height) {
int left = 0, right = height.length - 1;
int ans = 0;
int left_max = 0, right_max = 0;
while (left <= right) {
if (left_max < right_max) {
if (height[left] >= left_max) {
left_max = height[left];
} else {
ans += (left_max - height[left]);
}
++left;
} else {
if (height[right] >= right_max) {
right_max = height[right];
} else {
ans += (right_max - height[right]);
}
--right;
}
}
return ans;
}