1.能积水的底面一定不在四周,积水多少与周围最矮的立方体有关
2.围住中间积水的边界位置不一定在四周,所以“找出四周边界上最低的点直接求差”不可行
思路:
1.搜索队列使用优先级队列(堆),越低矮的点优先级越高(最小堆),越优先搜索
2.以矩形四周的点作为起始点(想象这个问题是水池外面有水,然后水面一点点升高,然后就会从水池高度低的地方向水池里面灌水,导致水池形成积水,积水处的水面就也会升高)进行广度优先搜索(这些点最初push进入队列)
3.使用一个二维数组对Push进入队列的点进行标记,之后搜索到该点后,不再PUSH进队列
4.只要队列不为空,即取出优先级队列队头元素进行搜索,按照上下左右四个方向进行拓展,拓展过程中忽略超出边界与已入队列的点
5.当对某点(x,y,h)拓展时,得到新的点(newx,newy)高度为heightMap[newx][newy],如果h>heightMap[newx][newy],则
结果+=h - heightMap[newx][newy],将heightMap[newx][newy],赋值为h(升高该位置的水面)。将(newx,newy,heightMap[newx][newy])push进队列,并做标记
扫描二维码关注公众号,回复:
1802266 查看本文章
还有,流进去的水不用担心会流出来
struct item{
int x;
int y;
int h;
item(int _x,int _y,int _h):x(_x),y(_y),h(_h){}
};
struct cmp{//这个可能会写错。。
bool operator()(const item& a,const item& b)
{
return a.h > b.h;
}
};
class Solution {
public:
int trapRainWater(vector<vector<int>>& heightMap) {
priority_queue<item, vector<item> ,cmp> q;
if(heightMap.size() <3 || heightMap[0].size() <3)
return 0;
int row = heightMap.size();
int col = heightMap[0].size();
vector<vector<int> >mark;
//初始化mark[][],以及将周边的点push进优先队列
for(int i = 0;i<row ; ++i)
{
mark.push_back(vector<int>());
for(int j = 0;j<col;++j)
mark[i].push_back(0);
}
for(int i =0;i<row;++i)
{//第一列和最后一列
q.push(item(i,0,heightMap[i][0]));
mark[i][0] = 1;
q.push(item(i,col-1,heightMap[i][col-1]));
mark[i][col-1] = 1;
}
for(int i = 1;i < col-1;++i)
{//第一行和最后一行
q.push(item(0,i,heightMap[0][i]));
mark[0][i] = 1;
q.push(item(row -1,i,heightMap[row-1][i]));
mark[row-1][i] = 1;
}
//搜索
static const int dx[] = {-1, 1 , 0, 0};
static const int dy[] = {0, 0, -1 , 1};
int res = 0;
while(!q.empty())
{
int x = q.top().x;
int y = q.top().y;
int h = q.top().h;
q.pop();
for(int i = 0;i < 4; ++i)
{
int newx = x + dx[i];
int newy = y + dy[i];
if(newx<0 || newx >= row || newy <0 || newy>=col || mark[newx][newy] ==1)
continue;
if( h > heightMap[newx][newy])
{
res = res + (h-heightMap[newx][newy]);//积水
heightMap[newx][newy] = h;
}
q.push(item(newx,newy,heightMap[newx][newy]));
mark[newx][newy] = 1;
}
}
return res;
}
};