42.接雨水
思路:两边比中间的高,就能留住雨水,先下降,再上升,取边界中小的作为水位线,从小的一端遍历到另一端减1的位置,就是水量,取值不知道怎么取
尝试(有想法,但是不全)
class Solution {
public int trap(int[] height) {
int len = height.length;
int[] stack = new int[len];
int res = 0;
Stack<Integer> stack = new Stack<>();
int temp = 0;
int popNum = 0;
for(int i =0; i<len; i++){
while(!stack.isEmpty()&&height[i]>stack.peek()){
temp+=stack.pop();
popNum++;
}
stack.push(height[i]);
}
}
}
答案
class Solution {
public int trap(int[] height){
int size = height.length;
if (size <= 2) return 0;
// in the stack, we push the index of array
// using height[] to access the real height
Stack<Integer> stack = new Stack<Integer>();
stack.push(0);
int sum = 0;
for (int index = 1; index < size; index++){
int stackTop = stack.peek();
if (height[index] < height[stackTop]){
stack.push(index);
}else if (height[index] == height[stackTop]){
// 因为相等的相邻墙,左边一个是不可能存放雨水的,所以pop左边的index, push当前的index
stack.pop();
stack.push(index);
}else{
//pop up all lower value
int heightAtIdx = height[index];
while (!stack.isEmpty() && (heightAtIdx > height[stackTop])){
int mid = stack.pop();
if (!stack.isEmpty()){
int left = stack.peek();
int h = Math.min(height[left], height[index]) - height[mid];
int w = index - left - 1;
int hold = h * w;
if (hold > 0) sum += hold;
stackTop = stack.peek();
}
}
stack.push(index);
}
}
return sum;
}
}
小结
注意,使用单调栈是在横向求解,我一开始想的是使用单调栈竖向求解,所以求不出来
84.柱状图中最大的矩形
题目:84. 柱状图中最大的矩形 - 力扣(LeetCode)
思路:取出非递减的数字,构成矩形
答案
class Solution {
int largestRectangleArea(int[] heights) {
Stack<Integer> st = new Stack<Integer>();
// 数组扩容,在头和尾各加入一个元素
int [] newHeights = new int[heights.length + 2];
newHeights[0] = 0;
newHeights[newHeights.length - 1] = 0;
for (int index = 0; index < heights.length; index++){
newHeights[index + 1] = heights[index];
}
heights = newHeights;
st.push(0);
int result = 0;
// 第一个元素已经入栈,从下标1开始
for (int i = 1; i < heights.length; i++) {
// 注意heights[i] 是和heights[st.top()] 比较 ,st.top()是下标
if (heights[i] > heights[st.peek()]) {
st.push(i);
} else if (heights[i] == heights[st.peek()]) {
st.pop(); // 这个可以加,可以不加,效果一样,思路不同
st.push(i);
} else {
while (heights[i] < heights[st.peek()]) { // 注意是while
int mid = st.peek();
st.pop();
int left = st.peek();
int right = i;
int w = right - left - 1;
int h = heights[mid];
result = Math.max(result, w * h);
}
st.push(i);
}
}
return result;
}
}
小结
- 以第 i 个柱子为高度,往两边扩展,找到左右两边比自己矮的,确定矩形的长度,得到矩形面积
- 我:先找到比较高的柱子
- 卡尔:挨个遍历柱子,计算result(以该柱子为高的矩形面积),用max取出最大
- 数组头部加入0,考虑【8,6,4,2】的情况,如果数组前面没有0,8入栈之后,遍历到6要进行计算时,不足三个元素(left,mid,right),无法得到结果
- 数组尾部加入0,考虑【2,4,6,8】的情况,入栈之后是 8,6,4,2】,找不到比栈口元素小的数字,无法触发计算,因此末尾要加上0
- ❗关键:挨个将柱子作为高,朝两边扩展,得到矩形