【广度优先搜索】【堆】【C++算法】407. 接雨水 II

news2024/10/7 14:31:05

作者推荐

【二分查找】【C++算法】378. 有序矩阵中第 K 小的元素

本文涉及知识点

广度优先搜索 堆

LeetCoce407. 接雨水 II

给你一个 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 * 104

广度优先搜索

vHeight记录各单格包括水的高度,初始为-1,表示未处理。四周边界显然无法留住水,所以四周边界的vHeight等于heightMap。
不断处理vHeight最小单格(r,c)的邻接单格(nr,nc) vHeight[nr][nc] = max(vHeight[r][c],heightMap[nr][nc]。
边界全部在已处理格子中。
{ 不会做什么 已处理格子的邻居都已经处理 不是边界 处理邻居 已处理格子有邻居未处理 边界 \begin{cases} 不会做什么 & 已处理格子的邻居都已经处理 & 不是边界 \\ 处理邻居 & 已处理格子有邻居未处理 & 边界\\ \end{cases} {不会做什么处理邻居已处理格子的邻居都已经处理已处理格子有邻居未处理不是边界边界
假定h1是边界最低vHeight,则任意未处理单格的水达到h1时,都不会流出。
h1所在单格的邻居水不会超过h1,否则会流到h1所在单格。

代码

核心代码

class CEnumGridEdge
{
public:
	void Init()
	{
		for (int r = 0; r < m_r; r++)
		{
			for (int c = 0; c < m_c; c++)
			{
				Move(r, c, r + 1, c);
				Move(r, c, r - 1, c);
				Move(r, c, r, c + 1);
				Move(r, c, r, c - 1);
			}
		}
	}
	const int m_r, m_c;
protected:
	CEnumGridEdge(int r, int c) :m_r(r), m_c(c)
	{

	}
	void Move(int preR, int preC, int r, int c)
	{
		if ((r < 0) || (r >= m_r))
		{
			return;
		}
		if ((c < 0) || (c >= m_c))

		{
			return;
		}
		OnEnumEdge(preR, preC, r, c);
	};
	virtual void OnEnumEdge(int preR, int preC, int r, int c) = 0;
};

class TNeiBoForGrid : public CEnumGridEdge
{
public:
	TNeiBoForGrid(const vector<vector<int>>& grid) :m_grid(grid),
		CEnumGridEdge(grid.size(), grid.front().size())
	{
		m_vNext.assign(m_r, vector < vector<pair<int, int>>>(m_c));
		Init();
	}
	virtual void OnEnumEdge(int preR, int preC, int r, int c)
	{	
		m_vNext[preR][preC].emplace_back(r, c);
	}
	const vector<vector<int>>& m_grid;
	vector < vector < vector<pair<int, int>>>> m_vNext;
};
class Solution {
public:
	int trapRainWater(vector<vector<int>>& heightMap) {
		TNeiBoForGrid neiBo(heightMap);
		vector<vector<int>> vHeight(neiBo.m_r, vector<int>(neiBo.m_c, -1));
		priority_queue<tuple<int, int, int>, vector<tuple<int, int, int>>, greater<>> minHeap;
		auto Add = [&](int r, int c, int iHeight)
		{
			if (vHeight[r][c] >= 0)
			{
				return;
			}
			vHeight[r][c] = iHeight;
			minHeap.emplace(iHeight, r, c);
		};
		for (int r = 0; r < neiBo.m_r; r++)
		{
			for (int c = 0; c < neiBo.m_c; c++)
			{
				if ((0 == r) || (neiBo.m_r == r + 1) || (0 == c) || (neiBo.m_c == c + 1))
				{
					Add(r, c, heightMap[r][c]);
				}
			}
		}
		while (minHeap.size())
		{
			auto [height, r, c] = minHeap.top();
			minHeap.pop();
			for (const auto& [nr, nc] : neiBo.m_vNext[r][c])
			{
				Add(nr, nc, max(height, heightMap[nr][nc]));
			}
		}
		int iRet = 0;
		for (int r = 0; r < neiBo.m_r; r++)
		{
			iRet += std::accumulate(vHeight[r].begin(), vHeight[r].end(), 0) - std::accumulate(heightMap[r].begin(), heightMap[r].end(), 0);
		}
		return iRet;
	}

};

测试用例

template<class T,class T2>
void Assert(const T& t1, const T2& t2)
{
	assert(t1 == t2);
}

template<class T>
void Assert(const vector<T>& v1, const vector<T>& v2)
{
	if (v1.size() != v2.size())
	{
		assert(false);
		return;
	}
	for (int i = 0; i < v1.size(); i++)
	{
		Assert(v1[i], v2[i]);
	}

}

int main()
{
	vector<vector<int>> heightMap;
	{
		Solution sln;
		heightMap = { {1,4,3,1,3,2},{3,2,1,3,2,4},{2,3,3,2,3,1} };
		auto res = sln.trapRainWater(heightMap);
		Assert(4, res);
	}
	
	{
		Solution sln;
		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} };
		auto res = sln.trapRainWater(heightMap);
		Assert(10, res);
	}

	
}

2023年3月

class Solution {
public:
int trapRainWater(vector<vector>& heightMap) {
m_r = heightMap.size();
m_c = heightMap[0].size();
//memset(m_arrNeiNum, 4, sizeof(m_arrNeiNum));
for (int c = 0; c < m_c; c++)
{
//m_arrNeiNum[0][c] = 1;
//m_arrNeiNum[m_r - 1][c] = 1;
AddRowColToRange(0, c, heightMap);
AddRowColToRange(m_r-1, c, heightMap);
}
for (int r = 1; r + 1 < m_r; r++)
{
AddRowColToRange(r,0, heightMap);
AddRowColToRange(r,m_c-1, heightMap);
//m_arrNeiNum[r][0] = 1;
//m_arrNeiNum[r][m_c - 1] = 1;
}
while (m_mHeightRowCol.size())
{
const int iHeight = m_mHeightRowCol.begin()->first;
const int r = m_mHeightRowCol.begin()->second / 1000;
const int c = m_mHeightRowCol.begin()->second % 1000;
Add(r + 1, c, iHeight,heightMap);
Add(r - 1, c, iHeight, heightMap);
Add(r, c + 1, iHeight, heightMap);
Add(r, c - 1, iHeight, heightMap);
m_mHeightRowCol.erase(m_mHeightRowCol.begin());
}
return m_iRet;
}
void Add(int r, int c, int iPreHeight, const vector<vector>& heightMap)
{
if ((r < 0) || (r >= m_r))
{
return;
}
if ((c < 0) || (c >= m_c))
{
return;
}
if (m_setHasDo.count(RowColMask(r,c)))
{
return;
}
const int iCurHeight = heightMap[r][c];
const int iWaterHeight = max(iCurHeight, iPreHeight);
if (iWaterHeight > iCurHeight)
{
m_iRet += iWaterHeight - iCurHeight;
}
AddRowColToRange(r, c, iWaterHeight);
}
void AddRowColToRange(int r, int c, const int iWaterHeight)
{
const int iRowCol = RowColMask(r, c);
m_mHeightRowCol.emplace(iWaterHeight, iRowCol);
m_setHasDo.insert(iRowCol);
}
void AddRowColToRange(int r, int c,const vector<vector>& heightMap)
{
AddRowColToRange(r, c, heightMap[r][c]);
}
inline int RowColMask(int r, int c)
{
return 1000 * r + c;
}
int m_r;
int m_c;
std::multimap<int, int> m_mHeightRowCol;//记录当前边界
std::unordered_set m_setHasDo;//记录已经处理的格子
std::unordered_set m_setNeiHasDo;//记录相邻格子已经处理完毕
//char m_arrNeiNum[200][200];//记录邻居数
int m_iRet = 0;

};

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771

如何你想快

速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

相关

下载

想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653

我想对大家说的话
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1494385.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

kerberos学习系列一:原理

1、简介 Kerberos 一词来源于古希腊神话中的 Cerberus —— 守护地狱之门的三头犬。 Kerberos 是一种基于加密 Ticket 的身份认证协议。Kerberos 主要由三个部分组成&#xff1a;Key Distribution Center (即KDC)、Client 和 Service。 优势&#xff1a; 密码无需进行网络传…

Tkinter实现聊天气泡对话框

功能展示&#xff1a; 运行环境&#xff1a; Python: 3.10.4 64-bit 操作系统&#xff1a;win10 64-bit 源码文件列表&#xff1a; 部分代码说明&#xff1a; 调用该接口将消息显示在聊天框中。role参数控制消息显示的位置&#xff1a;0位于对话框左边&#xff0c;1位于右边…

批次大小对ES写入性能影响初探

问题背景 ES使用bulk写入时每批次的大小对性能有什么影响&#xff1f;设置每批次多大为好&#xff1f; 一般来说&#xff0c;在Elasticsearch中&#xff0c;使用bulk API进行批量写入时&#xff0c;每批次的大小对性能有着显著的影响。具体来说&#xff0c;当批量请求的大小增…

LLM(十一)| Claude 3:Anthropic发布最新超越GPT-4大模型

2024年3月4日&#xff0c;Anthropic发布最新多模态大模型&#xff1a;Claude 3系列&#xff0c;共有Haiku、Sonnet和Opus三个版本。 Opus在研究生水平专家推理、基础数学、本科水平专家知识、代码等10个维度&#xff0c;超过OpenAI的GPT-4。 Haiku模型更注重效率&#xff0c;能…

Figma 最新版下载:无需激活码,轻松安装!

从事设计工作&#xff0c;怎么能没有设计工具呢&#xff1f;我相信许多设计师也必须使用Figma这样的软件&#xff0c;真的可以让我们的设计工作更有效率&#xff0c;但我相信你也发现Figma属于外国软件&#xff0c;自然语言也是英语&#xff0c;直到现在没有中文版本&#xff0…

论文解读:Hints for Thin Deep Nets

这篇论文是在Hinton的那篇开山之作《Distilling the Knowledge in a Neural Network》为背景提出来的&#xff0c;主要思想是使用一个宽而浅的教师模型来训练一个窄而深的学生模型。之前的知识蒸馏方法主要是训练教师网络到更浅更宽的网络&#xff0c;没有充分利用深度。而该文…

IntelliJ IDEA 下载安装及配置使用教程

一、IDEA下载 1、打开游览器输入IntelliJ IDEA – the Leading Java and Kotlin IDE (jetbrains.com) 2、点击Download&#xff0c;进入IDEA下载界面 3、 有两个版本&#xff0c;一个是Ultimate 版本为旗舰版&#xff0c;需要付费&#xff0c;包括完整的功能&#xff0c;下载后…

element-ui配置

全局配置 完整引入 Element&#xff1a; import Vue from vue; import Element from element-ui; Vue.use(Element, { size: small, zIndex: 3000 });按需引入 Element Vue.prototype.$ELEMENT { size: small, zIndex: 3000 };如果是vue.config.js中配置了externals 使用按…

设计师成长之路1

. 学习的书籍: 1.写给大家看的设计书 2,设计师要懂心理学 3,平面设计完全手册 4.去日本上设计课2:配色设计原理

【C++】102.二叉树的层序遍历

题目描述 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 示例1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[[3],[9,20],[15,7]]示例 2&#xff1…

fatal: unable to access ‘***‘: OpenSSL SSL_read: SSL_ERROR_SYSCALL, errno 0解决方案

本文收录于《AI绘画从入门到精通》专栏&#xff0c;专栏总目录&#xff1a;点这里。 大家好&#xff0c;我是水滴~~ 本文主要介绍在从 GitHub 上克隆 stable-diffusion-webui 项目时出现的 fatal: unable to access https://github.com/AUTOMATIC1111/stable-diffusion-webui.…

报错:module ‘collections‘ has no attribute ‘Iterable‘

使用python 高版本&#xff0c;在使用collections遇到报错&#xff1a;module ‘collections’ has no attribute ‘Iterable’ 查了资料 在python3.9 之后collections.Iterable被弃用了。 添加修改语句 collections.Iterable collections.abc.Iterable

【C++】String常用的函数总结

目录 一、string的构造函数方式&#xff1a; 二、常用的大小/容量相关操作&#xff1a; 三、string的常用修改操作&#xff1a; 四、string的遍历&#xff1a; 五、string的任意位置插入 / 删除&#xff1a; 六&#xff1a;补充&#xff1a; 一、string的构造函数方式&a…

Redis的三种集群模式(图解)

主从复制模式 一个主节点和多个从节点。主节点提供写入和读取功能&#xff0c;但是从属节点只提供读取功能。 主从复制的数据同步过程如下&#xff1a; &#xff08;1&#xff09;首先主节点启动&#xff0c;然后从属节点启动&#xff0c;从属节点会连接主节点并发送SYNC命令以…

SpringCloud Alibaba 学习

一&#xff1a;SpringCloud Alibaba介绍 Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用微服 务的必需组件&#xff0c;方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。 依托 Spring Cloud Alibaba&…

00X集——CAD vba 填充(hatch)及挖空

首先&#xff0c;画个椭圆&#xff0c;并填充&#xff0c;直接上代码&#xff1a; Sub 画椭圆填充() 2024年3月6日21:10:22 by qq443440204 Dim hat As AcadHatch 填充 Dim ell(0) As AcadEllipse 椭圆 Dim cent(0 To 2) As Double 椭圆中心点 Dim dd(0 To 2) As Double 椭圆长…

Android开发手册,android面试试题

前言 组件化是 保持整个 App 可持续地进行高质量开发的基础&#xff0c;近年来也是业界一直在积极探索和实践的方向&#xff0c;在深入理解组件化架构的过程中&#xff0c;将不断考验你的技术深度与广度&#xff1b;实践中我还参考了十几家技术团队的解决方案&#xff08;例如…

智能设备 app 设计 —— 蓝蓝 UI 设计公司

今天给大家推荐是智能设备app设计&#xff0c;随着智能设备的逐渐普及随之操作app也越来越多&#xff0c;希望能给大家带来灵感 #日常灵感 #创意设计#UI提升#ui设计#app #设计案例分享|#设计 #产品设计#产品设计#设计灵感 #B端产品经理 #ui #产品 #美工 #交互 #产品经理 #开发 …

android实战视频教程,细数Android开发者的艰辛历程

缘起 随着互联网企业的不断发展&#xff0c;产品项目中的模块越来越多&#xff0c;用户体验要求也越来越高&#xff0c;想实现小步快跑、快速迭代的目的越来越难&#xff0c;还有应用之间的互相调用等等问题&#xff0c;插件化技术应用而生。如果没有插件化技术&#xff0c;美…

64位Office API声明语句第116讲

跟我学VBA&#xff0c;我这里专注VBA, 授人以渔。我98年开始&#xff0c;从源码接触VBA已经20余年了&#xff0c;随着年龄的增长&#xff0c;越来越觉得有必要把这项技能传递给需要这项技术的职场人员。希望职场和数据打交道的朋友&#xff0c;都来学习VBA,利用VBA,起码可以提高…