1
+ // 407. 接雨水 II
2
+
3
+
4
+ /*
5
+ 优先级队列:外圈到内圈访问,逐渐缩小圈
6
+ 1、使用优先级队列存放外圈柱子三元组,即横坐标、纵坐标、高度,升序排序。因为木桶原理,内圈柱子能灌多少水取决于外圈最低柱子的高度
7
+ 访问数组标记柱子是否访问过,访问过则跳过
8
+ 2、初始化,将外圈柱子三元组存入队列,并标记已访问
9
+ 3、当队列不为空时,队列弹出元素为外圈最低柱子,遍历访问最低柱子的上下左右四个方向的柱子。四个方向的作用在于外圈有四个边界,各取所需访问到内圈柱子。
10
+ 方向数组把上下左右四个坐标压缩成一维数组,灵活获取坐标
11
+ 4、因为外圈都被访问了,如果坐标有效,则说明柱子在圈内,所以如果被访问的柱子 坐标有效并且未访问,
12
+ 那么再判断外圈最低柱子与圈内柱子的高度差,如果高度差大于0,说明圈内柱子可以灌水体积为高度差,否则不能灌水
13
+ 5、被访问过的内圈柱子将作为新的外圈柱子,加入到队列中,高度是外圈柱子与内圈柱子取较高者,并标记已访问
14
+ */
15
+ class Solution {
16
+ public int trapRainWater (int [][] heightMap ) {
17
+ int m = heightMap .length , n = heightMap [0 ].length ;
18
+ boolean [][] visited = new boolean [m ][n ];
19
+ PriorityQueue <int []> queue = new PriorityQueue <>((o1 , o2 ) -> o1 [2 ] - o2 [2 ]);
20
+ for (int i = 0 ; i < m ; i ++) {
21
+ for (int j = 0 ; j < n ; j ++) {
22
+ if (i == 0 || i == m - 1 || j == 0 || j == n - 1 ) {
23
+ queue .offer (new int [] {i , j , heightMap [i ][j ]});
24
+ visited [i ][j ] = true ;
25
+ }
26
+ }
27
+ }
28
+ int res = 0 ;
29
+ int [] dirs = {0 , -1 , 0 , 1 , 0 };
30
+ while (!queue .isEmpty ()) {
31
+ int [] minSide = queue .poll ();
32
+ for (int k = 0 ; k < 4 ; k ++) {
33
+ int x = minSide [0 ] + dirs [k ];
34
+ int y = minSide [1 ] + dirs [k + 1 ];
35
+ if (x >= 0 && x < m && y >= 0 && y < n && !visited [x ][y ]) {
36
+ int heighDiff = minSide [2 ] - heightMap [x ][y ];
37
+ if (heighDiff > 0 ) {
38
+ res += heighDiff ;
39
+ }
40
+ queue .offer (new int [] {x , y , Math .max (minSide [2 ], heightMap [x ][y ])});
41
+ visited [x ][y ] = true ;
42
+ }
43
+ }
44
+ }
45
+ return res ;
46
+ }
47
+ }
0 commit comments