返回
剖析LeetCode 42:接雨水——JavaScript栈解
前端
2023-10-04 02:34:45
深入剖析 LeetCode 42:雨水收集器
想象你被困在一个由柱子组成的迷宫中,每个柱子都有不同的高度。一场倾盆大雨过后,这些柱子形成了大小不一的容器,你必须计算出每个容器可以收集多少雨水。听起来很有趣,不是吗?这就是 LeetCode 42 问题的精髓所在。
雨水收集难题
LeetCode 42 要求我们计算给定柱子阵列中每个柱子可以收集的最大雨水量。为了解决这个问题,我们将踏上一个算法之旅,使用栈这个数据结构作为我们的有力助手。
栈的妙用
栈是一种先进后出的数据结构,非常适合解决 LeetCode 42 问题。我们将使用栈来存储柱子的索引,这些索引代表着容器的左边界。
当我们从左到右遍历柱子时,我们将遇到的情况分为两种:
- 遇到比栈顶柱子更高的柱子: 我们将该柱子的索引压入栈中,因为它可以作为更高容量容器的左边界。
- 遇到比栈顶柱子更低的柱子: 这表明当前柱子可以作为容器的右边界。我们弹出栈顶元素并计算出它所代表的容器可以收集的雨水量。
算法流程
- 使用栈存储柱子索引。
- 遍历柱子数组,从左到右。
- 如果当前柱子更高,则将其索引压入栈中。
- 如果当前柱子更低,则弹出栈顶元素并计算雨水量。
- 重复步骤 3 和 4,直到遍历完所有柱子。
算法复杂度
该算法的时间复杂度为 O(n),其中 n 是柱子的数量。这是因为我们只需要遍历一次柱子数组。空间复杂度也是 O(n),因为栈的最大大小为柱子的数量。
JavaScript 实现
/**
* LeetCode 42: 接雨水
*
* 使用栈来计算每个柱子最多能接多少雨水。
*
* @param {number[]} height 柱子的高度
* @return {number} 最多能接多少雨水
*/
const trap = (height) => {
// 使用栈来存储柱子的索引
const stack = [];
// 最多能接多少雨水
let maxWater = 0;
for (let i = 0; i < height.length; i++) {
// 当遇到一个比栈顶元素更高的柱子时,将其索引压入栈中
while (stack.length > 0 && height[i] > height[stack[stack.length - 1]]) {
// 弹出栈顶元素
const top = stack.pop();
// 如果栈不为空,则可以计算出可以接住的雨水量
if (stack.length > 0) {
const width = i - stack[stack.length - 1] - 1;
const height = Math.min(height[i], height[stack[stack.length - 1]]) - height[top];
maxWater += width * height;
}
}
// 将当前柱子的索引压入栈中
stack.push(i);
}
return maxWater;
};
例子
让我们考虑一个柱子高度数组:
height = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]
按照算法步骤,我们首先将栈初始化为空。然后,从左到右遍历柱子数组:
- 当我们遇到 1 时,我们将其索引 1 压入栈中。
- 当我们遇到 0 时,我们将其索引 2 压入栈中。
- 当我们遇到 2 时,我们将其索引 3 压入栈中。
- 当我们遇到 1 时,我们将其索引 4 压入栈中。
- 当我们遇到 0 时,我们将其索引 5 压入栈中。
- 当我们遇到 1 时,我们将其索引 6 压入栈中。
- 当我们遇到 3 时,它比栈顶元素 1 高。因此,我们将其索引 7 压入栈中。
- 当我们遇到 2 时,它比栈顶元素 3 低。因此,我们弹出栈顶元素 3 并计算雨水量。雨水量为 (7 - 6 - 1) * (min(3, 2) - 0) = 3。
- 当我们遇到 1 时,我们将其索引 8 压入栈中。
- 当我们遇到 2 时,它比栈顶元素 1 高。因此,我们将其索引 9 压入栈中。
- 当我们遇到 1 时,我们将其索引 10 压入栈中。
遍历完所有柱子后,栈中的元素为 [2, 6, 9, 10]。这意味着最后有四个容器,分别收集了 3、0、2 和 0 单位的雨水。因此,总共收集的雨水量为 3 + 0 + 2 + 0 = 5。
常见问题解答
- 为什么需要使用栈?
栈可以帮助我们有效地跟踪柱子高度并计算雨水量。它允许我们弹出栈顶元素并计算出较低柱子可以收集的雨水量。 - 是否需要考虑边界条件?
由于栈中始终存储着容器的左边界,因此我们不必担心边界条件。 - 时间复杂度是多少?
算法的时间复杂度为 O(n),其中 n 是柱子的数量。 - 空间复杂度是多少?
算法的空间复杂度为 O(n),因为栈的最大大小为柱子的数量。 - LeetCode 42 的变体有哪些?
存在许多 LeetCode 42 的变体,例如:- 接雨水 II:考虑二维柱子矩阵。
- 接雨水 III:考虑具有不同高度和方向的柱子。