42 -Trapping Rain Water 接雨水
42 -Trapping Rain Water 接雨水
问题描述
链接:https://leetcode.com/problems/trapping-rain-water/description/
Given
n
non-negative integers representing an elevation map where the width of each bar is1
, compute how much water it can trap after raining.给定n个非负的整数 代表相应位置柱子的高度,柱子的宽度为1,求柱子构成的容器中能储存多少雨水?
案例:
Input: height = [0,1,0,2,1,0,1,3,2,1,2,1] Output: 6 Explanation: The above elevation map (black section) is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped. 解释:
给定数组height = [0,1,0,2,1,0,1,3,2,1,2,1], 其代表的柱子构成的容器如上所示。上述容器从左到右的高度依次为height数组中相应的数值。
故 该容器能存储的水 为 1+4 + 1 = 6
基本思想
这是一道动态规划的题目,属于一维动态规划。假设height的元素数目为n,定义长度为n的数组dp
- dp[i] 表示 第i个柱子能盛多少的水。dp[i] 依赖于 [0~i-1]最高的柱子leftmax和 [i~n-1]最高的柱子rightmax,即依赖于左边最高的柱子和右边最高的柱子,其更新规则如下:
- 如果 min(leftmax, rightmax) < height[i], 说明该柱子高度太高,无法盛水
- 如果 min(leftmax, rightmax) > height[i], 则 dp[i] = 1 * (min(leftmax, rightmax)-height[i]) 注意柱子的高度为1
构建两个数组left, right, 长度为n,left[i] 表示 height[0~i-1] 中最高的柱子高度;right[i] 表示 height[i+1,n-1]中,最高的柱子,可以将时间复杂度降低为\(o(n)\),空间复杂度为\(o(n)\)
代码
C++
int trap(vector<int>& height) { int size = height.size(); if (size<=2) return 0; vector<int> dp(size, 0); vector<int> leftMax(size, 0); vector<int> rightMax(size, 0); leftMax[1] = height[0]; rightMax[size-2] = height[size -1]; //构建数组,分别存储height[i]左边最高的柱子和右边最高的柱子 for(int i=2;i<size;++i) { if (height[i-1]>leftMax[i-1]) { leftMax[i] = height[i-1]; } else { leftMax[i] = leftMax[i-1]; } } for(int i=size-3;i>=0;--i) { if (height[i+1] > rightMax[i+1]) { rightMax[i] = height[i+1]; } else { rightMax[i] = rightMax[i+1]; } } int res = 0; for(int i=1;i<(size-1);++i) { int temp = min(leftMax[i], rightMax[i]); if(temp>height[i]) dp[i] = (temp - height[i]); res += dp[i]; } return res; } };
python
def trap(self, height: List[int]) -> int: size = len(height) if size <= 2: return 0 dp = [0] * size leftMax = [0] * size rightMax = [0] * size leftMax[1] = height[0] rightMax[size-2] = height[size-1] res = 0 for i in range(2,size): leftMax[i] = max(leftMax[i-1], height[i-1]) for i in range(size-3, 0, -1): # 如何逆向生成序列 rightMax[i] = max(rightMax[i+1], height[i+1]) for i in range(1,size): dp[i] = max(0, min(leftMax[i], rightMax[i]) - height[i]) res += dp[i] return res
延伸
- 可以使用双指针法将空间复杂度进一步降低为O(n)
分类:
编程篇 / leetcode
, 编程篇
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了