力扣(leetcode) 407. 接雨水 II 3D接雨水

力扣(leetcode) 407. 接雨水 II 3D接雨水

给你一个 m x n 的矩阵,其中的值均为非负整数,代表二维高度图每个单元的高度,请计算图中形状最多能接多少体积的雨水。

示例 1:

复制代码
输入: heightMap = [[1,4,3,1,3,2],[3,2,1,3,2,4],[2,3,3,2,3,1]]
输出: 4
解释: 下雨后,雨水将会被上图蓝色的方块中。总的接雨水量为1+2+1=4。

示例 2:

复制代码
输入: heightMap = [[3,3,3,3,3],[3,2,2,2,3],[3,2,1,2,3],[3,2,2,2,3],[3,3,3,3,3]]
输出: 10

提示:

  • m == heightMap.length
  • n == heightMap[i].length
  • 1 <= m, n <= 200
  • 0 <= heightMap[i][j] <= 2 * 10^4

思路:

这道题的思路可以延续二维接雨水问题的思路,二维的情况下,我们用双指针的方法不断的缩小未被扫描到的范围,也就是被我们(用指针)划定的边界框起来的范围。在范围缩小的过程中,可以不断的得到一个新的确定接水量的柱子。

那么在三维的情况下,也可以延续这个思想。在三维中,边界 的划定不再是两个指针 (或者说两根柱子),而是用一圈柱子 。为什么是这样呢?因为我们可以发现,最周围一圈的柱子 肯定是无法接水的,那么它们就形成了初始的围栏 (边界)。我们知道一个道理"木桶装水的多少取决于最短的那块板的高度",这里也是这样,我们找到最短的那个围栏(柱子),它必然可以确定与它相邻的柱子的接水量。

怎么确定的呢?我们看下面这张图片:

图中,蓝色的围栏中,高度为4的柱子为最短的。那么,与他相邻的柱子(图中以红色显示),如果高度高于4,则该柱子无法接水(水会从4那里漏出去)。如果高度低于4,那么我们可以确定红色柱子接水后 柱子加上水 最高高度为4 。那最低高度呢?最低高度就得看它高度为4的水会不会流出去 ,而由于围栏最低高度都为4了 ,那么高度为4的水是无法通过围栏的,所以其最低高度也为4。也就是说,红色区域接水后的高度就等于4。(或者说高度已经被最短的那块围栏确定了)

利用最短围栏确定其领域接水高度的规则,我们可以依次确定红色区域的接水高度,然后将其加入到围栏当中,一直缩小围栏,就可以得到所有柱子的接水高度。

代码:

cpp 复制代码
typedef pair<int,int> P;
class Solution {
public:
    int trapRainWater(vector<vector<int>>& height) {
        int m=height.size(),n=height[0].size();
        int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
        vector<vector<bool> > vis(m,vector<bool>(n,false));
        priority_queue<P,vector<P>,greater<P> > que;
        for(int i=0;i<m;i++)
            for(int j=0;j<n;j++)
                if(i==0||j==0||i==m-1||j==n-1)
                {
                    que.push(make_pair(height[i][j],i*n+j));
                    vis[i][j]=true;
                }
        int total=0;
        while(!que.empty())
        {
            P cur=que.top();
            que.pop();
            for(int i=0;i<4;i++)
            {
                int x=cur.second/n,y=cur.second%n;
                int nx=x+dir[i][0],ny=y+dir[i][1];
                if(nx>=0&&nx<m&&ny>=0&&ny<n&&!vis[nx][ny])
                {
                    if(height[nx][ny]<cur.first)
                        total+=cur.first-height[nx][ny];
                    vis[nx][ny]=true;
                    que.push(make_pair(max(cur.first,height[nx][ny]),nx*n+ny));
                }
            }
        }
        return total;
    }
};
相关推荐
CM莫问1 小时前
<论文>(微软)避免推荐域外物品:基于LLM的受限生成式推荐
人工智能·算法·大模型·推荐算法·受限生成
康谋自动驾驶2 小时前
康谋分享 | 自动驾驶仿真进入“标准时代”:aiSim全面对接ASAM OpenX
人工智能·科技·算法·机器学习·自动驾驶·汽车
C++ 老炮儿的技术栈3 小时前
什么是函数重载?为什么 C 不支持函数重载,而 C++能支持函数重载?
c语言·开发语言·c++·qt·算法
yychen_java4 小时前
R-tree详解
java·算法·r-tree
MarkHard1234 小时前
Leetcode (力扣)做题记录 hot100(62,64,287,108)
算法·leetcode·职场和发展
一只鱼^_5 小时前
牛客练习赛138(首篇万字题解???)
数据结构·c++·算法·贪心算法·动态规划·广度优先·图搜索算法
一只码代码的章鱼5 小时前
Spring的 @Validate注解详细分析
前端·spring boot·算法
邹诗钰-电子信息工程5 小时前
嵌入式自学第二十一天(5.14)
java·开发语言·算法
↣life♚6 小时前
从SAM看交互式分割与可提示分割的区别与联系:Interactive Segmentation & Promptable Segmentation
人工智能·深度学习·算法·sam·分割·交互式分割
zqh176736464696 小时前
2025年阿里云ACP人工智能高级工程师认证模拟试题(附答案解析)
人工智能·算法·阿里云·人工智能工程师·阿里云acp·阿里云认证·acp人工智能