0と1に還元され
642 words
3 minutes
接雨水
Cover Image Source: Source
题目链接:42. 接雨水
思路
本题思路有动态规划、单调栈、双指针等,详见官方解答。这里提供一种动态规划和单调栈结合的方法。
总体思路
雨水面积可表示为
直接求和可以得出,因此关键在于如何求出。下面通过动态规划解决这个问题。
动态规划
用 表示仅存在下标在 之中的柱子时,柱子和雨水的面积之和。考虑添加第 i+1 号柱子。如果 中存在比第 i+1 号柱子更高的柱子,假设第 号柱子是这些柱子中最靠后的柱子,则
如果不存在,则找到 中最高的柱子,假设是第 号柱子,则
为了区分以上两种情况,用 表示第 i 号柱子之前不存在更高的柱子。
由此可以得出状态转移方程:
现在最大的问题是如何求出 。这里使用单调栈来求解。
单调栈
从右往左将数列中的元素加入单调递减栈,当单调性不满足时,将栈顶元素弹出直至满足单调性。每轮循环中,对于任意被弹出的元素 a ,新加入的元素 b 即为所有在 a 左侧且比 a 大的元素中距离 a 最近的元素。由此可求得 数组。
代码
代码如下:
class Solution {public: int trap(vector<int> &height) { int n = height.size(); stack<int> mono; // monotone stack vector<int> front(height.size(), 0); vector<int> dp(height.size() + 1, 0); int sum = 0; // 高度之和 int maxIndex = 0; // 当前高度最高的柱子
// 单调栈 for (int i = n - 1; i >= 0; --i) { sum += height[i]; front[i] = i; while (!mono.empty() && height[mono.top()] < height[i]) { front[mono.top()] = i; mono.pop(); } mono.push(i); }
dp[0] = height[0]; for (int i = 1; i < n; ++i) { if (front[i] < i) dp[i] = dp[front[i]] + height[i] * (i - front[i]); else // front[i] == i dp[i] = dp[maxIndex] + height[maxIndex] * (i - maxIndex - 1) + height[i];
maxIndex = height[i] > height[maxIndex] ? i : maxIndex; }
return dp[n - 1] - sum; }};评测结果
执行用时:16 ms, 在所有 C++ 提交中击败了54.90%的用户
内存消耗:20.6 MB, 在所有 C++ 提交中击败了5.04%的用户
通过测试用例:322 / 322