[Leetcode][407. 接雨水 II] 2种方法:优先队列存储每层围栏最低高度,BFS更新每个方块存水高度
By Long Luo
Leetcode 407. 接雨水 II 题目如下:
- 接雨水 II
给你一个 \(m \times 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
这道题是 42. 接雨水 的3D版本,区别于2D版本只需要维护左右两个最高的木板,这里需要维护一个围栏,用堆(优先队列)来维护周围这个围栏中的最小元素。
方法一:优先队列 + 最小堆
思路与算法:
因为需要维护一个圈,用来存储水,所以需要从矩阵的最外围往里面遍历,不断缩小圈,直到遍历每个方块,在这个过程中计算每个方块能装多少水,更新 \(\textit{ans}\) 。
那么什么方块能存水呢?
- 该方块不是在圈外;
- 该方块高度比其上下左右四个相邻的方块接水后的高度都要低。
假设方块的索引为 \((i,j)\),方块高度为 \(\textit{heightMap}[i][j]\),方块接水后的高度为 \(\textit{water}[i][j]\),则方块 \((i,j)\) 的接水后的高度为:
\[ \textit{water}[i][j] = \max( \textit{heightMap}[i][j], \min( \textit{water}[i-1][j], \textit{water}[i+1][j], \textit{water}[i][j-1], \textit{water}[i][j+1])) \]
每个方块 \((i,j)\) 实际接水量为:\(\textit{water}[i][j] - \textit{heightMap}[i][j]\)。
那问题变成了如何知道每个方块的 \(\textit{water}[i][j]\) 呢?
因为最外层的方块无法接水,所以最外层的方块接水后的高度 \(\textit{water}[i][j]=\textit{heightMap}[i][j]\);
根据木桶原理,而每层水的高度则取决于每层方块中高度最低的方块;
从矩阵的四周边界开始,则可以知道最外层方块接水后的高度最小值。之后遍历每层中的每个方块周围\(4\) 个方块,如果比当前方块低,那么说明这个方块可以接水,接水后的高度就是当前层的最小高度,反之更高的话,将其加入优先队列中;
更新最外层的方块标记,在新的最外层的方块再次找到接水后的高度的最小值,依次迭代直到求出所有的方块的接水高度,即可知道矩阵中的接水容量。