题目:
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.
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.
理论分析:
Min Heap
- 用PriorityQueue把选中的height排序,为走位, create class Cell (x,y, height).
注意几个理论
- 1. 从matrix四周开始考虑,发现matrix能Hold住的水,取决于height低的block
- 2. 必须从外围开始考虑,因为水是被包裹在里面,外面至少需要现有一层
- 以上两点就促使我们用min-heap: 也就是natural order的PriorityQueue<Cell>.
Steps
- 1. process的时候,画个图也可以搞清楚: 就是四个方向都走走,用curr cell的高度减去周围cell的高度.
- 2. 若大于零,那么周围的cell就有积水: 因为cell已经是外围最低, 所以内部更低的, 一定有积水.
- 3. 每个visited的cell都要mark, avoid revisit
- 4. 根据4个方向的走位 `(mX, mY)` 创建新cell 加进queue里面: cell(mX, mY) 已经计算过积水后, 外围墙小时, `(mX, mY)`就会变成墙.
- 5. 因为做的是缩小一圈的新围墙, height = Math.max(cell.h, neighbor.h);
- 和trapping water I 想法一样。刚刚从外围,只是能加到跟外围cell高度一致的水平面。往里面,很可能cell高度变化。
- 这里要附上curr cell 和 move-to cell的最大高度。
为什么想到用Heap (min-heap - priorityQueue)
- 要找到bucket的最短板
- 每次需要最先处理最短的那条 (on top)
为什么从外向里遍历
- 木桶理论, 包水, 是从外面包住里面
- 洋葱剥皮, 用完丢掉
class Solution {
public:
class cell{
public:
int x;
int y;
int h;
cell(int x,int y, int h)
{
this->x = x;
this->y = y;
this->h = h;
}
};
struct comp{
bool operator()(const cell &c1, const cell &c2)
{
return c1.h > c2.h;
}
};
int trapRainWater(vector<vector<int>>& heightMap) {
if(heightMap.size() == 0 || heightMap[0].size() == 0)
return 0;
int total = 0;
priority_queue<cell,vector<cell>,comp> que;
int m = heightMap.size();
int n = heightMap[0].size();
bool visited[110][110];
memset(visited,false,110*110);
for(int i = 0; i < m; i++)
{
visited[i][0] = true;
visited[i][n-1] = true;
que.push(cell(i,0,heightMap[i][0]));
que.push(cell(i,n-1,heightMap[i][n-1]));
}
for(int j = 0; j < n; j++)
{
visited[0][j] = true;
visited[m-1][j] = true;
que.push(cell(0,j,heightMap[0][j]));
que.push(cell(m-1,j,heightMap[m-1][j]));
}
int dx[] = {0,0,1,-1};
int dy[] = {1,-1,0,0};
while(!que.empty()){
cell c = que.top();
que.pop();
for(int i = 0; i < 4; i++){
int mx = c.x + dx[i];
int my = c.y + dy[i];
if(mx >= 0 && mx < m && my >= 0 && my < n && !visited[mx][my])
{
visited[mx][my] = true;
if(c.h > heightMap[mx][my])
{
total += c.h - heightMap[mx][my];
}
que.push(cell(mx,my,max(c.h,heightMap[mx][my])));
}
}
}
return total;
}
};