您的位置:首页 > 移动开发

leetcode 407. Trapping Rain Water II

2017-08-30 17:04 387 查看
Given an
m x n
matrix of positive integers representing the height of each unit cell in
a 2D elevation map, compute the volume of water it is able to trap after raining.

Note:

Both m and n are less than 110. The height of each unit cell is greater than 0 and is less than 20,000.

Example:
Given the following 3x6 height map:
[
[1,4,3,1,3,2],
[3,2,1,3,2,4],
[2,3,3,2,3,1]
]

Return 4.




The above image represents the elevation map
[[1,4,3,1,3,2],[3,2,1,3,2,4],[2,3,3,2,3,1]]
before
the rain.



After the rain, water are trapped between the blocks. The total volume of water trapped is 4.
这道题很有思维难度。
用一个 queue 来记录当前的 border。首先,把所有位于四周 border 的格子放入队列。然后从 queue 中取出最低的格子,然后 check its neighbors:

如果它的 neighbor (设为格子A) 更低,那么收集 A 能储住的水,将 A 的高度更新为储水后的高度,然后放入队列,作为新的 border。

如果它的 neighbor 更高或等高,那么把 neighbor 放入队列,作为新的 border。

这个算法的正确性在于:每次我们只检测当前墙壁中最低高度的那个,遍历是逐步从外墙壁到内墙壁。所以当你遇到一个 neighbor 比当前 poll 出的墙高度还要低时,你一定至少能在该 neighbor 点处储住
cell.height
- heights[row][col]
的水。 (remember that current cell we used are the one with the smallest height among the boarders).

package leetcode;

import java.util.Comparator;
import java.util.PriorityQueue;

public class Trapping_Rain_Water_II_407 {

public int trapRainWater(int[][] heightMap) {
if(heightMap.length<=2||heightMap[0].length<=2){
return 0;
}
int m=heightMap.length;
int n=heightMap[0].length;
int count=0;
boolean[][] visited=new boolean[m]
;
//queue中存储外围的墙
PriorityQueue<Cell> queue = new PriorityQueue<Cell>(1, new Comparator<Cell>() {
public int compare(Cell a, Cell b) {
return a.height - b.height;
}
});

for(int i=0;i<m;i++){
queue.offer(new Cell(i, 0, heightMap[i][0]));
visited[i][0]=true;
queue.offer(new Cell(i, n-1, heightMap[i][n-1]));
visited[i][n-1]=true;
}
for(int i=0;i<n;i++){
queue.offer(new Cell(0, i, heightMap[0][i]));
queue.offer(new Cell(m-1, i, heightMap[m-1][i]));
visited[0][i]=true;
visited[m-1][i]=true;
}
int[][] direction=new int[][]{
{-1,0},{0,-1},{1,0},{0,1}
};//上,左,下,右
while(!queue.isEmpty()){
Cell cell=queue.poll();
for(int i=0;i<4;i++){
int newX=cell.x+direction[i][0];
int newY=cell.y+direction[i][1];
if(newX<0||newX>=m||newY<0||newY>=n){
continue;
}
if(!visited[newX][newY]){
if(heightMap[newX][newY]>=heightMap[cell.x][cell.y]){
//将它作为新的墙
queue.offer(new Cell(newX, newY, heightMap[newX][newY]));
}
else{
count+=(heightMap[cell.x][cell.y]-heightMap[newX][newY]);
heightMap[newX][newY]=heightMap[cell.x][cell.y];
//水坑填满水后高度设为填完水之后的高度,可以看做是墙
queue.offer(new Cell(newX, newY, heightMap[newX][newY]));
}
visited[newX][newY]=true;
}
}
}
return count;
}

class Cell {
int x;
int y;
int height;
public Cell(int row, int col, int height) {
this.x = row;
this.y = col;
this.height = height;
}
}

}
这是大神的原版解法:

Source code from:
https://github.com/shawnfan/LintCode/blob/master/Java/Trapping Rain Water II.java
public class Solution {

public class Cell {
int row;
int col;
int height;
public Cell(int row, int col, int height) {
this.row = row;
this.col = col;
this.height = height;
}
}

public int trapRainWater(int[][] heights) {
if (heights == null || heights.length == 0 || heights[0].length == 0)
return 0;

PriorityQueue<Cell> queue = new PriorityQueue<>(1, new Comparator<Cell>(){
public int compare(Cell a, Cell b) {
return a.height - b.height;
}
});

int m = heights.length;
int n = heights[0].length;
boolean[][] visited = new boolean[m]
;

// Initially, add all the Cells which are on borders to the queue.
for (int i = 0; i < m; i++) {
visited[i][0] = true;
visited[i][n - 1] = true;
queue.offer(new Cell(i, 0, heights[i][0]));
queue.offer(new Cell(i, n - 1, heights[i][n - 1]));
}

for (int i = 0; i < n; i++) {
visited[0][i] = true;
visited[m - 1][i] = true;
queue.offer(new Cell(0, i, heights[0][i]));
queue.offer(new Cell(m - 1, i, heights[m - 1][i]));
}

// from the borders, pick the shortest cell visited and check its neighbors:
// if the neighbor is shorter, collect the water it can trap and update its height as its height plus the water trapped
// add all its neighbors to the queue.
int[][] dirs = new int[][]{{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
int res = 0;
while (!queue.isEmpty()) {
Cell cell = queue.poll();
for (int[] dir : dirs) {
int row = cell.row + dir[0];
int col = cell.col + dir[1];
if (row >= 0 && row < m && col >= 0 && col < n && !visited[row][col]) {
visited[row][col] = true;
res += Math.max(0, cell.height - heights[row][col]);
queue.offer(new Cell(row, col, Math.max(heights[row][col], cell.height)));
}
}
}

return res;
}
}

还有大神说可以看看youtube上的动态图解视频来直观地了解解法,但是貌似那个解法不是上面的解法?
总之有兴趣可以看看(要搭梯子),网址:https://www.youtube.com/watch?v=cJayBq38VYw

我截了点图,顺序是一层层从左往右看。可以点开链接看清晰大图。http://img.blog.csdn.net/20170830170703057

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: