407. 接雨水 II

308 阅读1分钟

这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战

407. 接雨水 II

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

 

  • 示例 1:

image.png

输入: 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:

image.png

输入: 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  

提示:

  • m == heightMap.length
  • n == heightMap[i].length
  • 1 <= m, n <= 200
  • 0 <= heightMap[i][j] <= 2 * 10^4

解题思路

维护一个高度从小到大的优先队列,因为根据木桶原理,接雨水的量是由四周最矮的木桶决定的,所以我们每次从优先队列中取出一个当前高度最小的cur,遍历它的四周的4个格子next,如果出现比当前高度cur还小的next,则说明可以往这个格子里面灌水,因为假如next周围存在比它矮的low,我们可以继续向矮的格子low灌水,因为我们的cur是从优先队列里面取出来的最小值,并且优先队列是有矩阵的边际元素组成,也就是说,只要是小于cur的格子我们都可以灌水,而不用担心水会从边界漏出。

代码

typedef  pair<int,int> p;
class Solution {
public:
    int trapRainWater(vector<vector<int>>& heightMap) {

        int n=heightMap.size(),m=heightMap[0].size();
        if (n<=2||m<=2)
            return 0;
        priority_queue<p,vector<p>,greater<p>> priorityQueue;
        vector<vector<bool>> visited(n,vector<bool>(m, false));

        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < m; ++j) {
                if (i==0||j==0||i==n-1||j==m-1)
                {
                    priorityQueue.push({heightMap[i][j],i*m+j});
                    visited[i][j]=true;
                }    
                
            }
        }
        int res=0;
        int dir[]{-1,0,1,0,-1};
        while (!priorityQueue.empty())
        {
            p cur=priorityQueue.top();
            priorityQueue.pop();
            int cx=cur.second/m,cy=cur.second%m;
            for (int i = 0; i <=3; ++i) {
                int nx=cx+dir[i],ny=cy+dir[i+1];
                if (nx>=0&&nx<n&&ny>=0&&ny<m&&!visited[nx][ny]){
                    if (cur.first>heightMap[nx][ny])
                        res+=cur.first-heightMap[nx][ny];
                    priorityQueue.push({max(cur.first,heightMap[nx][ny]),nx*m+ny});
                    visited[nx][ny]= true;
                }
            }

        }
        return res;
    }
};