一、题目:42. 接雨水
难度:hard
给定 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
- 1 <= n <= 2 * 104
- 0 <= height[i] <= 105
二、解法
解法1:面积法
class Solution {
// 1. 面积法
public int trap(int[] height) {
// 左侧
int leftMax = 0;// 最大值
int s1 = 0;// 绿色部分面积
// 右侧
int rightMax = 0;// 最大值
int s2 = 0;// 黄色部分面积
// 计算绿色部分面积
for (int i = 0; i < height.length; i++) {
leftMax = Math.max(leftMax, height[i]);
s1 += leftMax;
}
// 计算黄色部分面积
for (int i = height.length - 1; i >= 0; i--) {
rightMax = Math.max(rightMax, height[i]);
s2 += rightMax;
}
// 柱子面积 (紫色部分)
int colArea = Arrays.stream(height).sum();
// 整体面积 (红细线圈出的长方形)
int overallArea = leftMax * height.length;
// 雨水面积=s1+s2-整体面积-围墙面积
return s1 + s2 - overallArea - colArea;
}
}
解答成功:
执行耗时:3 ms,击败了33.00% 的Java用户
内存消耗:43.3 MB,击败了31.17% 的Java用户
以上解法改编自:https://leetcode.cn/problems/trapping-rain-water/solution/by-ddz16-5c0s/
解法2:双指针
class Solution {
// 2. 双指针解法
public int trap(int[] height) {
// 返回值,雨水总量
int ans = 0;
// 左右指针
int left = 0;
int right = height.length - 1;
// 左右最大值
int leftMax = 0, rightMax = 0;
// 计算雨水量
while (left < right) {
// 哪边小,哪边接雨水
if(height[left] < height[right]){
// 从左往右,依次更新左边柱子最大值
leftMax = Math.max(leftMax, height[left]);
// 雨水总量 累加 当前可接雨水量 (左侧最大值-当前柱子高度)
ans += leftMax - height[left];
// 左指针右移
left++;
}else {
// 从右往左,依次更新右边柱子最大值
rightMax = Math.max(rightMax, height[right]);
// 雨水总量 累加 当前可接雨水量 (右侧最大值-当前柱子高度)
ans += rightMax - height[right];
// 右指针左移
right--;
}
}
return ans;
}
}
解答成功:
- 执行耗时:0 ms,击败了100.00% 的Java用户
- 内存消耗:43.7 MB,击败了9.00% 的Java用户
- 以上解法转载于:https://leetcode.cn/problems/trapping-rain-water/solution/jie-yu-shui-by-leetcode-solution-tuvc/
- 注释是我个人添加
三、后记
今天AC了一道hard,成就感满满,继续加油啊!!!