单调栈or动态规划——接雨水
原题在这里:
概述题意,给一个数组,求填平数组(凹处的高低差)所需面积。
想过双指针两端考虑高点收缩;
想过从每一个高度入手;
也想过单调栈(但没想明白怎么用)。
然后debug一个小时用了一个自己的解法:
去重找峰值,删除峰的凹峰【此后数组类型就是(递增+)递减了】,然后遍历。

class Solution { vector<int> num, m; vector<int> pick() { vector<int> n(0); int l = m.size(); if (l > 2) { if (num[m[0]] > num[m[1]]) n.emplace_back(m[0]); for (int i = 1; i < l - 1; ++i) if (num[m[i]] > num[m[i - 1]] && num[m[i]] > num[m[i + 1]]) n.emplace_back(m[i]); if (num[m[l - 1]] > num[m[l - 2]]) n.emplace_back(m[l - 1]); return n; } return m; } public: int trap(vector<int> &height) { int ans = 0, l = height.size(); for (int i = 0; i < l; ++i) { num.emplace_back(height[i]); if (i == 0 || height[i] != height[i - 1]) m.emplace_back(i); } m = pick(); for (int i = 1, mx = height[m[0]]; i < m.size() - 1; ++i) { mx = max(mx, height[m[i]]); if (mx > height[m[i]] && height[m[i]] < height[m[i + 1]]) m.erase(m.begin() + i), i = max(i - 2, 0); } l = m.size(); //处理完后只有(递增+)递减 for (int i = 1; i < l; ++i) { int x = m[i - 1], y = m[i]; for (int j = x + 1; j < y; ++j) ans += max(min(num[x], num[y]) - num[j], 0); } return ans; } };
比较满意的一点是,解法是线性复杂度的。
然后看官解一如既往的优秀:
1.动态规划
一图看懂:
简直太棒了,两端遍历维护最大值,然后遍历min[i]-num[i]即可,很直观的O(n)解法。
完全是数学类型解法,优秀。
code:

class Solution { public: int trap(vector<int> &height) { int ans = 0, l = height.size(); if (l > 2) { vector<int> left(height), right(height); for (int i = 1; i < l; ++i) left[i] = max(left[i], left[i - 1]); for (int i = l - 2; i >= 0; --i) right[i] = max(right[i], right[i + 1]); for (int i = 0; i < l; ++i) ans += min(left[i], right[i]) - height[i]; } return ans; } };
2.单调栈
当前高度小于等于栈顶高度,入栈,指针后移。
当前高度大于栈顶高度,出栈,计算出当前墙和栈顶的墙之间水的多少,然后计算当前的高度和新栈的高度的关系,重复第 2 步。
直到当前墙的高度不大于栈顶高度或者栈空,然后把当前墙入栈,指针后移。
code:

class Solution { public: int trap(vector<int> &height) { int ans = 0, l = height.size(); stack<int> st; for (int i = 0; i < l; ++i) { while (!st.empty() && height[st.top()] < height[i]) { int left = st.top(); st.pop(); if (st.empty()) break; int l = st.top(); ans += (i - l - 1) * (min(height[i], height[l]) - height[left]); } st.push(i); } return ans; } };
3.双指针
如上。
【Over】
大
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
· 零经验选手,Compose 一天开发一款小游戏!