2023.7.23 接雨水
一个能接雨水的区域,肯定是两边高,中间低,基于这个前提出发就能得到两种做法。
动态规划
预处理出每个柱子左边最高的柱子,同时也处理出每个柱子右边的最高的柱子。两者取一个min,记做h。那么如果h比当前柱子更高,那么起码当前这个柱子就可以在垂直领域上可以存下h - 当前柱子高
个单位的水。
对每个柱子都进行这样的计算,累计贡献即为答案。
use std::cmp::{max, min};
impl Solution {
pub fn trap(height: Vec<i32>) -> i32 {
let n = height.len();
let mut left_max = vec![0; n];
let mut right_max = vec![0; n];
left_max[0] = height[0];
for i in 1..n {
left_max[i] = max(left_max[i - 1], height[i]);
}
right_max[n - 1] = height[n - 1];
for i in (0..n-1).rev() {
right_max[i] = max(right_max[i + 1], height[i]);
}
let mut res = 0;
for i in 0..n {
res += min(left_max[i], right_max[i]) - height[i];
}
res
}
}
单调栈
每一个两边高中间低的区域,都可以接一定量的雨水,那么我们可以构建一个高度单调递减的单调栈。
假设当前遍历到柱子i,它的高度比栈顶柱子的高度更高,那么不满足单调递减,退栈,再退栈的过程中,由于单调栈内部单调递减,假设栈顶为top,那么有宽度\*(两边高度-栈顶柱子的高度)
。
涉及到下标计算的话,Rust会有一堆类型转换很难看,用C++实现。
class Solution {
public:
int trap(vector<int>& height)
{
int n = height.size();
int stk[n + 1], top = 0;
int res = 0;
for (int i = 0; i < n; ++i)
{
while (top && height[i] > height[stk[top]])
{
--top;
if (top)
res += (i - stk[top] - 1) * (min(height[i], height[stk[top]]) - height[stk[top + 1]]);
}
stk[++top] = i;
}
return res;
}
};
作者:st0rmKR
出处:https://www.cnblogs.com/st0rmKR/p/17574820.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具