接雨水
接雨水(Trapping Rain Water)是一个经典的算法问题,题目要求在给定的非负整数数组中,每个元素的值代表地形的高度,求这个地形能够接住多少雨水。
public class TrapRainWater {
public int trap(int[] height) {
int n = height.length;
if (n == 0) return 0;
int[] leftMax = new int[n]; // 存储每个位置左边的最大高度
int[] rightMax = new int[n]; // 存储每个位置右边的最大高度
// 计算每个位置左边的最大高度
leftMax[0] = height[0];
for (int i = 1; i < n; i++) {
leftMax[i] = Math.max(leftMax[i - 1], height[i]);
}
// 计算每个位置右边的最大高度
rightMax[n - 1] = height[n - 1];
for (int i = n - 2; i >= 0; i--) {
rightMax[i] = Math.max(rightMax[i + 1], height[i]);
}
int totalWater = 0;
// 计算每个位置能够接住的雨水量
for (int i = 0; i < n; i++) {
int minHeight = Math.min(leftMax[i], rightMax[i]);
// 如果当前位置高度小于左右两边的最大高度,说明能接住雨水
if (height[i] < minHeight) {
totalWater += minHeight - height[i];
}
}
return totalWater;
}
}
解释每一步:
-
首先定义两个数组
leftMax
和rightMax
,分别用于存储每个位置左边和右边的最大高度。 -
遍历数组,计算每个位置左边的最大高度,存储在
leftMax
数组中。 -
再次遍历数组,计算每个位置右边的最大高度,存储在
rightMax
数组中。 -
遍历数组,计算每个位置能够接住的雨水量。对于每个位置,找到它左右两边最大高度的较小值,减去当前位置的高度,即为当前位置能接住的雨水量。
-
将每个位置能接住的雨水量累加,得到总的雨水量。
这种解法的时间复杂度为 O(n),其中 n 是数组的长度。因为我们需要遍历数组三次,每次遍历的时间复杂度都是 O(n)。空间复杂度为 O(n),因为我们使用了两个额外的数组来存储每个位置左右两边的最大高度。