题目:
给定 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
提示:
n == height.length
0 <= n <= 3 * 104
0 <= height[i] <= 105
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/trapping-rain-water
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路:
方法1: 暴力
很明显每个柱子顶部可以储水的高度为:该柱子的左右两侧最大高度的较小者减去此柱子的高度。
因此我们只需要遍历每个柱子,累加每个柱子可以储水的高度即可。
此方法非常好理解,直接看下述👇代码中的注释即可。
方法2: 单调栈
简单来说就是当前柱子如果小于等于栈顶元素,说明形不成凹槽,则将当前柱子入栈;反之若当前柱子大于栈顶元素,说明形成了凹槽,于是将栈中小于当前柱子的元素pop出来,将凹槽的大小累加到结果中。
具体思路清参考:
甜姨的题解。
https://mp.weixin.qq.com/s/f9ebzbwymR8jQeUDxjeCDA
方法3:面积做差。
解法来源:参考lc 宫水三叶,详情请见
https://leetcode-cn.com/problems/volume-of-histogram-lcci/solution/gong-shui-san-xie-yi-ti-si-jie-po-su-yu-sqadp/
//暴力
class Solution {
public int trap(int[] height) {
int res = 0;
// 遍历每个柱子
for (int i = 1; i < height.length - 1; i++) {
int leftMax = 0, rightMax = 0;
// 计算当前柱子左侧的柱子中的最大高度
for (int j = 0; j <= i; j++) {
leftMax = Math.max(leftMax, height[j]);
}
// 计算当前柱子右侧的柱子中的最大高度
for (int j = i; j < height.length; j++) {
rightMax = Math.max(rightMax, height[j]);
}
// 结果中累加当前柱子顶部可以储水的高度,
// 即 当前柱子左右两边最大高度的较小者 - 当前柱子的高度。
res += Math.min(leftMax, rightMax) - height[i];
}
return res;
}
}
//单调栈
class Solution {
public boolean find132pattern(int[] nums) {
Stack<Integer> s = new Stack<Integer>();
int n = nums.length;
int k = Integer.MIN_VALUE;
for (int i = n - 1; i >= 0; i--) {
if (nums[i] < k) {
return true;
}
//自主控制弹出,来实现单调栈
while ((!s.empty ()) && (s.peek() < nums[i])) {
k = Math.max (k, s.pop());
}
s.push (nums[i]);
}
return false;
}
}
//面积作差
class Solution {
public int trap(int[] height) {
//spcial
int sum = 0;
int len = height.length;
int max = 0;
for (int i = 0; i < len; i++) {
sum += height[i];
max = Math.max (height[i], max);
}
int full = max * len;
int lSum = 0;
max = 0;
for (int i = 0; i < len; i++) {
max = Math.max (height[i], max);
lSum += max;
}
int rSum = 0;
max = 0;
for (int i = len - 1; i >= 0; i--) {
max = Math.max (height[i], max);
rSum += max;
}
return rSum + lSum - full - sum;
}
}