package com.tang.project1.utils;
import java.util.Stack;
public class LeetCode42 {
static class Solution {
public static int trap(int[] height) {
//砖头的数目小于3都没法组成凹槽,没法装水,所以水的面积是0
if(height.length < 3) return 0;
Stack<Integer> stack = new Stack<>();
//保存水的面积
int res = 0;
//遍历height数组
for(int i = 0;i < height.length;i++){
//如果栈是空的,就可以将当前的数的数组下标压入栈中
if(stack.isEmpty()){
stack.push(i);
//如果将要压入的栈中的数,小于等于当前的栈顶元素,也将将当前的数的数组下标压入栈中
}else if(height[i] <= height[stack.peek()]){
stack.push(i);
}else{
//当栈中的值不为空,并且将要压入的栈中的数大于当前的栈顶元素
while(!stack.isEmpty()&&height[i] > height[stack.peek()]){
//假如height[i]是下标为3的砖头
//那么bottom就是下标为2的砖头
int bottom = stack.peek();
//把下标为2的砖头弹出栈中
stack.pop();
//此时栈中不为空,即凹槽的左侧存在元素
if(!stack.isEmpty()){
//算出水的面积,先算出高,用左右两边高度最小的砖头高度减去底部的砖头,就可以得到水的高度,如上图下标为1的砖头和下标为3的砖头取高度较小的,减去下标为2的底部砖头
//因为上面已经弹出了一块砖头,所以此时height[stack.peek()]是下标为1的砖头
int h = Math.min(height[i],height[stack.peek()]) - height[bottom];
//stack.peek()是下标为1的砖头,3 - 1 - 1,最后一个减1是,计算宽度都要减的。
int w = i - stack.peek() - 1;
//res面积是累加的
res += h * w;
}
}
//用于比如第一个数是0 第二个数是1的情况,第一次循环0压入栈中,第二次循环,跳到else分支,在stack.pop()以后栈为空,但是此时1还是要入栈的,所以用stack.push(i);将1压入栈中
stack.push(i);
}
}
//将结果返回
return res;
}
}
public static void main(String[] args) {
int[] height = {0,1,0,2,1,0,1,3,2,1,2,1};
System.out.println(Solution.trap(height));
}
}