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 is 1, 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

延伸

  1. 可以使用双指针法将空间复杂度进一步降低为O(n)
posted @   金字塔下的蜗牛  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示