这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战
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
提示:
- 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;
}
};