方法一
实现思路
实现思路,是基于【LeetCode42】-接雨水的思路,不同点在于不仅要考虑上下左右的最大值,同时也要考虑斜着的最大值最小值,针对每一个点,取这些最大值的最小值减去该点的高度值,就可以得到最终的结果
实现代码(待补充)
这个代码是有些不完善的,现在是只考虑上下左右的最大值,而没有考虑斜着的最大值,这种作法有待补充和优化
class Solution {
public:
bool inner(int row,int column,int x,int y){
return x>=0&&x<row&&y>=0&&y<column;
}
/*
void getleft_right_max(vector<int> &data,vector<int> &l,vector<int> &r){
int n=data.size();
for(int j=0;j<n;j++)
l[j]=j==0?data[j]:max(l[j-1],data[j]);
for(int j=n-1;j>=0;j--)
r[j]=j==n-1?data[j]:max(r[j+1],data[j]);
}
void set_data(bool reverse,int ff){
int xx=1;
int yy=1;
if(reverse) xx=-1;
vector<int> &l,vector<int> &r;
int x,y;
}*/
int trapRainWater(vector<vector<int>>& heightMap) {
//border
int row=heightMap.size();
if(!row) return 0;
int column=heightMap[0].size();
if(!column) return 0;
vector<vector<int>> l(row,vector<int>(column)),r(row,vector<int>(column)),t(row,vector<int>(column)),b(row,vector<int>(column)),lr(row,vector<int>(column)),rl(row,vector<int>(column));
//set left and right
for(int i=0;i<row;i++){
for(int j=0;j<column;j++)
l[i][j]=j==0?heightMap[i][j]:max(l[i][j-1],heightMap[i][j]);
for(int j=column-1;j>=0;j--)
r[i][j]=j==column-1?heightMap[i][j]:max(r[i][j+1],heightMap[i][j]);
}
//set top and bottom
for(int i=0;i<column;i++){
for(int j=0;j<row;j++){
t[j][i]=j==0?heightMap[j][i]:max(t[j-1][i],heightMap[j][i]);
}
for(int j=row-1;j>=0;j--){
b[j][i]=j==row-1?heightMap[j][i]:max(b[j+1][i],heightMap[j][i]);
}
}
int ans=0;
for(int i=0;i<row;i++){
for(int j=0;j<column;j++){
cout<<i<<" "<<j<<":"<<l[i][j]<<","<<r[i][j]<<","<<t[i][j]<<","<<b[i][j]<<endl;
ans+=max(min(min(l[i][j],r[i][j]),min(t[i][j],b[i][j]))-heightMap[i][j],0);
}
}
return ans;
}
};
未通过的样例
[[12,13,1,12],[13,4,13,12],[13,8,10,12],[12,13,12,12],[13,13,13,13]]
方法二(带优先级的搜索)
实现思路
思想概述起来,就是想象逐渐升高,从边界最小的数值开始取起来,当周围的元素在里面的情况下,就将该元素可积水量进行记录,在宽搜的过程中记得将已经遍历的点标记
这个思路是本方法的重点,就是使用一种逆向思维的思考方式,想象将水往里流,水在进行一种广搜
实现代码
struct Qitem{
int x;
int y;
int h;
Qitem(int x,int y,int h):x(x),y(y),h(h){;}
};
struct cmp{
bool operator() (const Qitem &a,const Qitem &b){
return a.h>b.h;
}
};
class Solution {
public:
int trapRainWater(vector<vector<int>>& heightMap) {
int row=heightMap.size();
if(!row) return 0;
int column=heightMap[0].size();
if(row<3||column<3) return 0;
vector<vector<int>> book(row,vector<int>(column,0));
//init
priority_queue<Qitem,vector<Qitem>,cmp> q;
for(int i=0;i<row;i++){
book[i][0]=1;
q.push(Qitem(i,0,heightMap[i][0]));
book[i][column-1]=1;
q.push(Qitem(i,column-1,heightMap[i][column-1]));
}
for(int j=1;j<column-1;j++){
book[0][j]=1;
q.push(Qitem(0,j,heightMap[0][j]));
book[row-1][j]=1;
q.push(Qitem(row-1,j,heightMap[row-1][j]));
}
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
int ans=0;
//main
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 tx=x+dx[i];
int ty=y+dy[i];
if(tx<0||tx>=row||ty<0||ty>=column||book[tx][ty]) continue;
if(h>heightMap[tx][ty]){
ans+=h-heightMap[tx][ty];
heightMap[tx][ty]=h;
}
q.push(Qitem(tx,ty,heightMap[tx][ty]));
book[tx][ty]=1;
}
}
return ans;
}
};
提交结果及分析
主要时间复杂度应该就是在于遍历所有的结点
总结
要学会逆向思维来进行解题,要掌握带优先级的宽度优先遍历的方法