1. LeetCode 42. 接雨水
题目链接:https://leetcode.cn/problems/trapping-rain-water/description/
文章链接:https://programmercarl.com/0042.接雨水.html#思路
视频链接:https://www.bilibili.com/video/BV1uD4y1u75P/
思路:
1.如果当前遍历的元素(柱子)高度小于栈顶元素的高度:就把这个元素加入栈中,因为栈里本来就要保持从小到大的顺序(从栈头到栈底);
2.如果当前遍历的元素(柱子)高度等于栈顶元素的高度:要更新栈顶元素,因为遇到相相同高度的柱子,需要使用最右边的柱子来计算宽度。
3.如果当前遍历的元素(柱子)高度大于栈顶元素的高度,此时就出现凹槽了:
- a.栈顶元素,就是凹槽的底部,也就是中间位置,下标记为mid,对应的高度为height[mid]
- b.栈顶元素下一个元素,就是凹槽的左边位置,下标为left,对应的高度为height[left]。
- c.当前遍历的元素i,就是凹槽右边的位置,下标为i,对应的高度为height[i]。
- 雨水高度是:min(凹槽左边高度, 凹槽右边高度) - 凹槽底部高度,代码为:int h = min(height[left], height[i]) - height[mid];
- 雨水的宽度是:凹槽右边的下标 - 凹槽左边的下标 - 1(因为只求中间宽度),代码为:int w = i - left - 1 ;
当前凹槽雨水的体积就是:h * w。
解法:
class Solution {
public int trap(int[] height) {
Deque<Integer> stack = new ArrayDeque<>();
if (height.length == 1) {
return 0;
}
int sum=0;//雨水总和
stack.push(0);
for (int i=1;i<height.length;i++) {
if (height[stack.peek()] > height[i]) {
stack.push(i);
} else if (height[stack.peek()] == height[i]) {
stack.pop();
stack.push(i);
} else {
while (!stack.isEmpty() && height[stack.peek()] < height[i]) {
int mid = stack.pop();
if (!stack.isEmpty()) {
int right = i;
int left = stack.peek();
int h = Math.min(height[right],height[left]) - height[mid];
int w = right - left - 1;
sum += h * w;
}
}
stack.push(i);
}
}
return sum;
}
}
LeetCode 84.柱状图中最大的矩形
题目链接:https://leetcode.cn/problems/largest-rectangle-in-histogram/description/
文章链接:https://programmercarl.com/0084.柱状图中最大的矩形.html
视频链接:https://www.bilibili.com/video/BV1Ns4y1o7uB/
思路:
本题是要找每个柱子左右两边第一个小于该柱子的柱子,所以从栈头(元素从栈头弹出)到栈底的顺序应该是从大到小的降序顺序!
处理逻辑:
1.如果当前遍历的元素(柱子)高度大于栈顶元素的高度:就把这个元素加入栈中,因为栈里本来就要保持从大到小的顺序(从栈头到栈底);
2.如果当前遍历的元素(柱子)高度等于栈顶元素的高度:要更新栈顶元素,因为遇到相相同高度的柱子,需要使用最右边的柱子来计算宽度。
3.如果当前遍历的元素(柱子)高度小于栈顶元素的高度:
- a.栈顶元素,就是中间位置,下标记为mid,对应的高度为height[mid]
- b.栈顶元素下一个元素,就是左边位置,下标为left,对应的高度为height[left]。
- c.当前遍历的元素i,就是右边的位置,下标为i,对应的高度为height[i]。
面积的高度是:height[mid];
面积的宽度是:右边的下标 - 左边的下标 - 1(因为只求中间宽度),代码为:int w = i - left - 1 ;
当前位置的面积就是:h * w。
注意:使用的数组进行了扩充,前后各扩充了一个单位,数值为0,这是防止数组本身是降序或者升序所导致的res=0的情况。
解法:
class Solution {
public int largestRectangleArea(int[] heights) {
Deque<Integer> stack = new ArrayDeque<>();
int[] newHeight = new int[heights.length+2];
for (int i=0;i<heights.length;i++) {
newHeight[i+1] = heights[i];
}
stack.push(0);
int res = 0;
for (int i=1;i<newHeight.length;i++) {
if (newHeight[stack.peek()] < newHeight[i]) {
stack.push(i);
} else if (newHeight[stack.peek()] == newHeight[i]) {
stack.pop();
stack.push(i);
} else {
while (!stack.isEmpty() && newHeight[stack.peek()] > newHeight[i]) {
int mid = stack.pop();
if (!stack.isEmpty()) {
int left = stack.peek();
int right = i;
int h = newHeight[mid];
int w = right - left - 1;
res = Math.max(res,h * w);
}
}
stack.push(i);
}
}
return res;
}
}