持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第21天。
题目链接: leetcode.com/problems/tr…
1. 题目介绍(Trapping Rain Water)
Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it can trap after raining.
【Translate】: 给定n个非负整数,表示一个高度图,其中每个条的宽度为1,计算它在下雨后可以捕获多少水。
【测试用例】:
【约束】:
2. 题解
2.1 Brute-Force
代码来自junhaowanggg的 [Java] Detailed Explanations & Illustrations (divide-and-conquer, DP, two pointers),以[4,2,0,3,2,5]为例,暴力求解从数组0索引开始,逐步寻找两边最大的墙,然后通过Math.min(leftMax, rightMax)减去当前值得到该位置所能存储的水量,直至结束。
class Solution {
public int trap(int[] height) {
int n = height.length;
int totalWater = 0;
for (int k = 0; k < n; ++k) {
int leftMax = 0;
for (int i = 0; i <= k - 1; ++i) {
leftMax = Math.max(leftMax, height[i]);
}
int rightMax = 0;
for (int i = k + 1; i < n; ++i) {
rightMax = Math.max(rightMax, height[i]);
}
int water = Math.min(leftMax, rightMax) - height[k];
totalWater += (water > 0) ? water : 0;
}
return totalWater;
}
}
2.2 Two pointer
- 在这里,我们将使用两个指针l和r来遍历数组,并使用leftmax和rightmax来存储向左和向右的最大值。
- 我们需要明白的是,只有在有山谷时,我们才能在总和中添加水。
- 因此,当遍历时,如果我们发现高度[l]小于或等于高度[r],那么我们就知道,只有height[l]也小于leftmax时,才能存储水。
其实这就相当于左右开工,逐渐向中间逼近。
class Solution {
public int trap(int[] height) {
int n = height.length;
if(n <= 2) return 0;
int sum = 0;
int l = 0, r = n - 1;
int leftMax = 0, rightMax = 0;
while(l < r) {
if(height[l] <= height[r]) {
if(height[l] >= leftMax) leftMax = height[l];
else {
sum += leftMax - height[l];
}
l++;
} else {
if(height[r] >= rightMax) rightMax = height[r];
else {
sum += rightMax - height[r];
}
r--;
}
}
return sum;
}
}