LeetCode 42 接雨水
在算法和数据结构中,有一类问题被称为“接雨水”问题,它们通常涉及在给定的某种地形(通常是表示为数组)上模拟雨水下降后的积水情况。其中一个经典的接雨水问题就是给定一个柱状图,计算下雨之后能接多少雨水。
在本文中,我们将讨论如何使用单调栈(Monotonic Stack)解决这个问题。单调栈是一种常见的数据结构,它可以帮助我们在O(n)的时间复杂度内解决一些与单调性相关的问题。
问题描述
给定n个非负整数,表示每个宽度为1的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
单调栈解决方案
我们将使用单调栈来解决这个问题。单调栈的基本思想是维护一个单调递增或单调递减的栈,以便于在需要时找到比当前元素更大或更小的元素。
算法解释
- 我们维护一个栈
st
,其中存放的是柱子的索引。 - 我们遍历每个柱子的高度。
- 如果当前柱子的高度大于栈顶柱子的高度,说明可能会有积水产生。我们弹出栈顶的柱子,直到当前柱子的高度小于等于栈顶柱子的高度或者栈为空。
- 在每次弹出栈顶柱子的时候,我们计算这个坑的面积,即当前柱子和栈顶的前一个柱子之间的区域能容纳的雨水量。
- 最后,我们将所有积水的面积相加,即得到了总的雨水量。
算法实现
下面是C++的实现代码:
class Solution {
public:int trap(vector<int>& height) {int v = 0;stack<int> st;st.push(0);for (int i = 1; i < height.size(); i++) {while (!st.empty() && height[i] > height[st.top()]) {int cur = st.top();st.pop();if (st.empty()) break; // 栈空则无法形成一个完整的坑int lift = st.top();int right = i;int h = min(height[right], height[lift]) - height[cur];int w = right - lift - 1;v += h * w;}st.push(i);}return v;}
};
复杂度分析
时间复杂度分析
- 遍历数组: 在算法中,我们需要遍历给定的高度数组,这一步骤的时间复杂度为O(n),其中n是数组的长度。
- 单调栈操作: 在单调栈的操作中,每个柱子最多被压入和弹出栈一次。因为每个柱子最多被处理一次,所以对于每个柱子的处理的时间复杂度是O(1)。在最坏情况下,每个柱子都可能被压入和弹出栈,所以单调栈的操作总体时间复杂度也是O(n)。
因此,总体上,该单调栈解法的时间复杂度为O(n)。
空间复杂度分析
- 单调栈的额外空间: 在算法中,我们使用了一个单调栈来存储柱子的索引。在最坏情况下,栈可能包含所有的柱子,因此单调栈的空间复杂度是O(n)。
因此,该单调栈解法的空间复杂度为O(n)。
总结
使用单调栈算法可以有效地解决接雨水问题,其时间复杂度为O(n),空间复杂度为O(n),其中n是柱子的数量。这种方法利用了栈的单调性质,使得我们可以在线性时间内解决这个问题,是一个高效且常用的解决方案。