【算法训练】LeetCode#42 接雨水
一、描述
42. 接雨水
给定 n
个非负整数表示每个宽度为 1
的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
示例 1:
输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。
示例 2:
输入:height = [4,2,0,3,2,5]
输出:9
二、思路
- 只想到了一种笨方法,逐一加入高度,当加入高度大于等于上一区域的max时,计算雨水,并更新max。
- 上面的方法没实现出来,其实想法是对的,但是卡在了左边界的设置上,其实不用纠结于“上一区域”,只需要将“洼地”的左侧节点作为边界,组成一个小型洼地计算出面积即可。
三、解题
public static class Solution {
public int trap(int[] height) {
int n = height.length; // 长度
int area = 0;
Deque<Integer> stack = new LinkedList<>(); // 双向队列模拟栈
for (int i = 0 ; i < n ; i++){
while (!stack.isEmpty() && height[i] > height[stack.peek()]){
// 当栈不为空且当前高度大于栈顶高度时进入循环。 栈顶作为洼地
int bottomLoc = stack.pop();
if (stack.isEmpty()){
// 当栈空时,表明洼地没有左侧边界,无法构成完整洼地,直接break
break;
}
int leftLoc = stack.peek(); // 因为height[i]>height[bottom]时,才有可能构成洼地,因此栈内的元素一定是大于等于height[bottom]的
int weight = i - leftLoc - 1; // 洼地长
int high = Math.min(height[i],height[leftLoc]) - height[bottomLoc]; // 洼地高,左右边界的高度最小值减低洼处的高度
area += weight * high; // 面积
}
stack.push(i);
}
return area;
}
}