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;
    }
};

方法二:并查集

相关文章
|
算法 计算机视觉 开发者
|
Linux Shell 网络安全
【Shell 命令集合 网络通讯 】Linux 与SMB服务器进行交互 smbclient命令 使用指南
【Shell 命令集合 网络通讯 】Linux 与SMB服务器进行交互 smbclient命令 使用指南
461 1
青龙脚本集合
青龙脚本集合
2131 0
|
SQL 存储 安全
如何在Java中进行安全编码?
如何在Java中进行安全编码?
|
算法
LeetCode150道面试经典题-移除元素(简单)
给你一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,并返回移除后数组的新长度
134 0
|
Java
leetcode-1049. 最后一块石头的重量 II
leetcode-1049. 最后一块石头的重量 II
109 0
|
消息中间件 缓存 网络协议
使用 Netty+SpringBoot 打造的 TCP 长连接通讯方案 上
使用 Netty+SpringBoot 打造的 TCP 长连接通讯方案 上
使用 Netty+SpringBoot 打造的 TCP 长连接通讯方案 上
|
前端开发 JavaScript