leetcode-407:接雨水 II

简介: leetcode-407:接雨水 II

题目

题目连接

给你一个 m x n 的矩阵,其中的值均为非负整数,代表二维高度图每个单元的高度,请计算图中形状最多能接多少体积的雨水。

示例 1:

输入: heightMap = [[1,4,3,1,3,2],[3,2,1,3,2,4],[2,3,3,2,3,1]]
输出: 4
解释: 下雨后,雨水将会被上图蓝色的方块中。总的接雨水量为1+2+1=4。

示例 2:

输入: heightMap = [[3,3,3,3,3],[3,2,2,2,3],[3,2,1,2,3],[3,2,2,2,3],[3,3,3,3,3]]
输出: 10

解题

动态规划(此方法在三维中没法用)

很快就想到将动态规划的方法从二维的接雨水引申到三维的接雨水中,但是存在侧漏的情况,如果仅仅只是求4个方向最高是不行的。

比如一个三维图的左视图和主视图都是这个样子,那么中心那个柱子,可以放3格水吗?显然会发生侧漏

class Solution {
public:
    inline int minH(int a,int b,int c,int d){
        return min(min(a,b),min(c,d));
    }
    int trapRainWater(vector<vector<int>>& heightMap) {
        int m=heightMap.size(),n=heightMap[0].size();
        vector<vector<int>> heightW(m,vector<int>(n,0));
        vector<vector<int>> heightS(m,vector<int>(n,0));
        vector<vector<int>> heightA(m,vector<int>(n,0));
        vector<vector<int>> heightD(m,vector<int>(n,0));
        for(int j=0;j<n;j++) heightW[0][j]=heightMap[0][j];
        for(int i=1;i<m;i++){
            for(int j=0;j<n;j++){
                heightW[i][j]=max(heightW[i-1][j],heightMap[i][j]);
            }
        }
        for(int j=0;j<n;j++) heightS[m-1][j]=heightMap[m-1][j];
        for(int i=m-2;i>=0;i--){
            for(int j=0;j<n;j++){
                heightS[i][j]=max(heightS[i+1][j],heightMap[i][j]);
            }
        }
        for(int i=0;i<m;i++) heightA[i][0]=heightMap[i][0];
        for(int j=1;j<n;j++){
            for(int i=0;i<m;i++){
                heightA[i][j]=max(heightA[i][j-1],heightMap[i][j]);
            }
        }
        for(int i=0;i<m;i++) heightD[i][n-1]=heightMap[i][n-1];
        for(int j=n-2;j>=0;j--){
            for(int i=0;i<m;i++){
                heightD[i][j]=max(heightD[i][j+1],heightMap[i][j]);
            }
        }
        int res=0;
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                res+=minH(heightA[i][j],heightD[i][j],heightW[i][j],heightS[i][j])-heightMap[i][j];
            }
        }
        return res;   
    }
};

方法一:优先队列

核心思想就是先确定木桶的外围,找到外围的最短板子后对其周围能填水的地方填水,然后更新木桶外围

根据木桶原理,接到的雨水由容器周围最短的木板决定的,开始取决于最外圈

通过优先队列,每次可以取到最短的木板

将3填充成了水,变成4,可以把它当作成新的容器的外圈,这样一步步迭代

class Solution {
public:
    int trapRainWater(vector<vector<int>>& heightMap) {
        int m=heightMap.size(),n=heightMap[0].size();
        priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> q;
        vector<vector<bool>> visited(m,vector<bool>(n,false));
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(i==0||i==m-1||j==0||j==n-1){
                    q.emplace(heightMap[i][j],i*n+j);
                    visited[i][j]=true;
                }
            }
        }
        int dirs[5]={-1,0,1,0,-1};
        int res=0;
        while(!q.empty()){
            auto [h,index]=q.top();
            q.pop();
            for(int i=0;i<4;i++){
                int nx=index/n+dirs[i];
                int ny=index%n+dirs[i+1];
                if(nx<0||nx>=m||ny<0||ny>=n||visited[nx][ny]) continue;
                if(heightMap[nx][ny]<h){
                    res+=h-heightMap[nx][ny];
                }
                visited[nx][ny]=true;
                q.emplace(max(heightMap[nx][ny],h),nx*n+ny);
            }
        }
        return res;
    }
};

方法二:并查集

相关文章
|
4月前
|
图计算 索引
leetcode-42:接雨水
leetcode-42:接雨水
29 0
|
7月前
|
算法 测试技术 图计算
|
4月前
|
容器
每日一题——接雨水(单调栈)
每日一题——接雨水(单调栈)
|
5月前
|
图计算
【每日一题Day274】LC42接雨水 | 单调栈
【每日一题Day274】LC42接雨水 | 单调栈
21 0
|
6月前
|
算法
【LeetCode力扣】42. 接雨水
【LeetCode力扣】42. 接雨水
35 0
|
9月前
|
机器学习/深度学习 人工智能 移动开发
Acwing 1574. 接雨水
Acwing 1574. 接雨水
41 0
|
11月前
|
算法 安全 Swift
LeetCode - #42 接雨水(Top 100)
不积跬步,无以至千里;不积小流,无以成江海,Swift社区 伴你前行。如果大家有建议和意见欢迎在文末留言,我们会尽力满足大家的需求。
LeetCode - #42 接雨水(Top 100)
|
11月前
|
测试技术
Leecode 42. 接雨水
Leecode 42. 接雨水
65 1
|
12月前
|
算法 图计算 C++
每日算法系列【LeetCode 42】接雨水
每日算法系列【LeetCode 42】接雨水
|
存储 算法 JavaScript
双指针解决【接雨水】问题
本篇将带来双指针算法经典题目之:接雨水问题;