今日收获:接雨水,柱状图中最大的矩形
1. 接雨水
题目链接:42. - 力扣(LeetCode)
思路:能接雨水需要形成凹槽,求的是左边和右边分别大于当前元素的第一个元素。
(1)利用单调栈从左到右的遍历过程中,如果当前元素比栈顶元素大,那么当前元素就是比栈顶元素大的右边第一个元素,栈顶元素的下一个元素就是比栈顶元素大的左边第一个元素,
(2)取两者之中的最小值作为雨水的高度,两者之间的下标差是雨水的宽度,相当于按行计算雨水。
方法:
class Solution {
public int trap(int[] height) {
int len=height.length;
Stack<Integer> stack=new Stack<>();
int result=0;
stack.push(0);
for (int i=1;i<len;i++){
if (height[i]<height[stack.peek()]){
stack.push(i);
}else {
while (!stack.isEmpty() && height[i]>height[stack.peek()]){
int mid=stack.pop();
if (!stack.isEmpty()){
int left=stack.peek();
int h=Math.min(height[i],height[left])-height[mid];
int x=i-left-1;
result+=h*x;
}
}
stack.push(i);
}
}
return result;
}
}
2. 柱状图中最大的矩形
题目链接:84. - 力扣(LeetCode)
思路:和接雨水正好相反,求的是左边和右边分别比当前元素小的下标。
(1)利用单调递减栈,两边比中间元素小的元素下标是能形成长方形的宽度边界,中间元素的高就是当前元素的值。
(2)首尾加0是为了防止数组本身就是有序的,不能计算结果。
方法:
class Solution {
public int largestRectangleArea(int[] heights) {
int max=0;
// 原数组首尾加0
int len=heights.length;
int[] newNums=new int[len+2];
for (int i=0;i<len;i++){
newNums[i+1]=heights[i];
}
Stack<Integer> stack=new Stack<>();
stack.push(0);
for (int i=1;i<len+2;i++){
if (newNums[i]>newNums[stack.peek()]){
stack.push(i);
}else {
while (!stack.isEmpty() && newNums[i]<newNums[stack.peek()]){
int mid=stack.pop();
int left=stack.peek();
int w=i-left-1;
max=Math.max(max,w*newNums[mid]);
}
stack.push(i);
}
}
return max;
}
}