C++二分算法:水位上升的泳池中游泳

涉及知识点

二分查找 并集查找或BFS。

题目

在一个 n x n 的整数矩阵 grid 中,每一个方格的值 grid[i][j] 表示位置 (i, j) 的平台高度。
当开始下雨时,在时间为 t 时,水池中的水位为 t 。你可以从一个平台游向四周相邻的任意一个平台,但是前提是此时水位必须同时淹没这两个平台。假定你可以瞬间移动无限距离,也就是默认在方格内部游动是不耗时的。当然,在你游泳的时候你必须待在坐标方格里面。
你从坐标方格的左上平台 (0,0) 出发。返回 你到达坐标方格的右下平台 (n-1, n-1) 所需的最少时间 。
示例 1:
输入: grid = [[0,2],[1,3]]
输出: 3
解释:
时间为0时,你位于坐标方格的位置为 (0, 0)。
此时你不能游向任意方向,因为四个相邻方向平台的高度都大于当前时间为 0 时的水位。
等时间到达 3 时,你才可以游向平台 (1, 1). 因为此时的水位是 3,坐标方格中的平台没有比水位 3 更高的,所以你可以游向坐标方格中的任意位置
示例 2:
输入: grid = [[0,1,2,3,4],[24,23,22,21,5],[12,13,14,15,16],[11,17,18,19,20],[10,9,8,7,6]]
输出: 16
解释: 最终的路线用加粗进行了标记。
我们必须等到时间为 16,此时才能保证平台 (0, 0) 和 (4, 4) 是连通的
参数范围
n == grid.length
n == grid[i].length
1 <= n <= 50
0 <= grid[i][j] < n2
grid[i][j] 中每个值 均无重复

分析

时间复杂度

O(log(nn)nn)。二分查找时间复杂度O(log(nn)),Can函数时间复杂度约O(n*n)。

Can函数

t时刻,起点和终点是否能连通。相邻的两个单格grid[r][c]和grid[r1][c1]如果都小于等于t,则连通。用并集查找或BFS判断起点和终点是否连通。只需要判断向右和向下的路径,向左和向上的路径必定有对应的向右或向下的路径。

二分

如果t时刻,符合要求;则t+1一定符合。对应符合要求的t,我们要找到最小值。故用左开右闭空间,t的取值范围[0,nn-1],左开右闭就是(-1,nn-1]

易错点

for (int r = 0; r  < m_c; r++) 

r < m_c 不能写成r+1<m_c,最后一行不能下移,可以右移。
计算掩码封装成函数,减少错误。

代码

核心代码

class CUnionFind
{
public:
CUnionFind(int iSize) :m_vNodeToRegion(iSize)
{
for (int i = 0; i < iSize; i++)
{
m_vNodeToRegion[i] = i;
}
m_iConnetRegionCount = iSize;
}
int GetConnectRegionIndex(int iNode)
{
int& iConnectNO = m_vNodeToRegion[iNode];
if (iNode == iConnectNO)
{
return iNode;
}
return iConnectNO = GetConnectRegionIndex(iConnectNO);
}
void Union(int iNode1, int iNode2)
{
const int iConnectNO1 = GetConnectRegionIndex(iNode1);
const int iConnectNO2 = GetConnectRegionIndex(iNode2);
if (iConnectNO1 == iConnectNO2)
{
return;
}
m_iConnetRegionCount–;
if (iConnectNO1 > iConnectNO2)
{
UnionConnect(iConnectNO1, iConnectNO2);
}
else
{
UnionConnect(iConnectNO2, iConnectNO1);
}
}
bool IsConnect(int iNode1, int iNode2)
{
return GetConnectRegionIndex(iNode1) == GetConnectRegionIndex(iNode2);
}
int GetConnetRegionCount()const
{
return m_iConnetRegionCount;
}
vector GetNodeCountOfRegion()//各联通区域的节点数量
{
const int iNodeSize = m_vNodeToRegion.size();
vector vRet(iNodeSize);
for (int i = 0; i < iNodeSize; i++)
{
vRet[GetConnectRegionIndex(i)]++;
}
return vRet;
}
std::unordered_map<int, vector> GetNodeOfRegion()
{
std::unordered_map<int, vector> ret;
const int iNodeSize = m_vNodeToRegion.size();
for (int i = 0; i < iNodeSize; i++)
{
ret[GetConnectRegionIndex(i)].emplace_back(i);
}
return ret;
}
private:
void UnionConnect(int iFrom, int iTo)
{
m_vNodeToRegion[iFrom] = iTo;
}
vector m_vNodeToRegion;//各点所在联通区域的索引,本联通区域任意一点的索引,为了增加可理解性,用最小索引
int m_iConnetRegionCount;
};

class Solution {
public:
int swimInWater(vector<vector>& grid) {
m_c = grid.size();
int left = -1, right = m_c * m_c - 1;
while (right - left > 1)
{
const int mid = left + (right - left) / 2;
if (Can(grid, mid))
{
right = mid;
}
else
{
left = mid;
}
}
return right;
}
bool Can(const vector<vector>& grid, int t)
{
CUnionFind uf(m_c * m_c);
for (int r = 0; r < m_c; r++)
{
for (int c = 0; c < m_c; c++)
{
if (grid[r][c] > t)
{
continue;
}
if ((c+1<m_c)&&(grid[r][c + 1] <= t))
{
uf.Union(Mask(r,c), Mask(r, c+1));
}
if ((r + 1 < m_c) && (grid[r +1 ][c] <= t))
{
uf.Union(Mask(r, c), Mask(r + 1, c ));
}
}
}
return uf.IsConnect(0, m_c * m_c - 1);
}
int Mask(int r, int c)
{
return m_c * r + c;
}
int m_c;
};

测试用例

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

template
void Assert(const vector& v1, const vector& 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> grid;
int res = 0;
{
Solution slu;
grid = { {0,1,2,3,4},{24,23,22,21,5},{12,13,14,15,16},{11,17,18,19,20},{10,9,8,7,6} };
res = slu.swimInWater(grid);
Assert(16, res);
}
{
Solution slu;
grid = { {0,2},{1,3} };
res = slu.swimInWater(grid);
Assert(3, res);
}

//CConsole::Out(res);
}

2023年3月旧代码

class Solution {
public:
int swimInWater(vector<vector>& grid) {
m_r = grid.size();
m_c = grid[0].size();
int left = -1, right = 50 * 50 - 1;
while (right > left + 1)
{
const int iMid = left + (right - left) / 2;
if (CanVisit(grid, iMid))
{
right = iMid;
}
else
{
left = iMid;
}
}
return right;
}
bool CanVisit(const vector<vector>& vWater,int t)
{
vector<vector> vHasDo(m_r, vector(m_c));
std::queue<std::pair<int, int>> queRowCol;
Move(0, 0, vHasDo, queRowCol,vWater,t);
while (queRowCol.size())
{
const int r = queRowCol.front().first;
const int c = queRowCol.front().second;
queRowCol.pop();
if ((r + 1 == m_r) && (c + 1 == m_c))
{
return true;
}
Move(r+1, c, vHasDo, queRowCol, vWater,t);
Move(r-1, c, vHasDo, queRowCol, vWater,t);
Move(r, c+1, vHasDo, queRowCol, vWater,t);
Move(r, c-1, vHasDo, queRowCol, vWater,t);
}
return false;
}
void Move(int r, int c, vector<vector>& vHasDo, std::queue<std::pair<int, int>>& queRowCol, const vector<vector>& vWater,int t )
{
if ((r < 0) || (r >= m_r))
{
return;
}
if ((c < 0) || (c >= m_c))
{
return;
}
if (vWater[r][c] >t )
{
return;
}
if (vHasDo[r][c])
{
return;
}
vHasDo[r][c] = true;
queRowCol.emplace(r, c);
}
int m_r, m_c;
};

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步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

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Oracle Unifier 22.12 ~ 23.10 功能改进清单表

序言 时隔近一年&#xff0c;Oracle Unifier 22还没握熟&#xff0c;新版本23便已迭代到23.10&#xff0c;根据甲骨文常规的发布规律&#xff0c;相信不久之后便会正式迎来正式本地版V23&#xff0c;了解Unfier的朋友或许知晓&#xff0c;本地版是云版迭代一年后的版本&#x…

SSM 线上知识竞赛系统-计算机毕设 附源码 27170

SSM线上知识竞赛系统 摘 要 科技进步的飞速发展引起人们日常生活的巨大变化&#xff0c;电子信息技术的飞速发展使得电子信息技术的各个领域的应用水平得到普及和应用。信息时代的到来已成为不可阻挡的时尚潮流&#xff0c;人类发展的历史正进入一个新时代。在现实运用中&#…

Go进阶之rpc和grpc

文章目录 Go环境安装1&#xff09;windows2&#xff09;linux go语言编码规范1.1 包名&#xff1a;package1.2 ⽂件名1.3 结构体命名1.4 接⼝命名1.5 变量命名1.6 常量命名2.1 包注释2.2 结构&#xff08;接⼝&#xff09;注释2.3 函数&#xff08;⽅法&#xff09;注释2.4 代码…

Flink架构

1、Apache Flink集群的核心架构&#xff1a; 1、client&#xff08;作业客户端&#xff09;&#xff1a;提交任务的地方叫做客户端 2、JobManager&#xff08;作业管理器&#xff09;&#xff1a;作用是用于管理集群中任务 3、TaskManager&#xff08;任务管理器&#xff09;&a…

内网可达网段探测netspy- Mac环境

netspy是一款快速探测内网可达网段工具 当我们进入内网后想要扩大战果&#xff0c;那我们可能首先想知道当前主机能通哪些内网段。 netspy正是一款应用而生的小工具&#xff0c;体积较小&#xff0c;速度极快&#xff0c;支持跨平台&#xff0c;支持多种协议探测&#xff0c;…

ZZ308 物联网应用与服务赛题第E套

2023年全国职业院校技能大赛 中职组 物联网应用与服务 任 务 书 &#xff08;E卷&#xff09; 赛位号&#xff1a;______________ 竞赛须知 一、注意事项 1.检查硬件设备、电脑设备是否正常。检查竞赛所需的各项设备、软件和竞赛材料等&#xff1b; 2.竞赛任务中所使用的…

财报解读:抢滩“睡眠经济”,麒盛科技如何制胜市场?

现代市场经济理论的鼻祖亚当斯密曾说&#xff0c;有需求就有市场&#xff0c;有市场才有发展。 调查研究显示&#xff0c;我国超3亿人存在睡眠障碍&#xff0c;其中超3/4的人晚11点以后入睡&#xff0c;近1/3的人熬到凌晨1点以后才能入睡。针对“睡个好觉”需求的“睡眠经济”…

Qt开发流程

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 例如&#xff1a;…

11-08 周三 图解机器学习之实现逻辑异或,理解输出层误差和隐藏层误差项和动量因子

11-08 周三 图解机器学习之实现逻辑异或&#xff0c;理解输出层误差和隐藏层误差项 时间版本修改人描述2023年11月8日14:36:36V0.1宋全恒新建文档 简介 最近笔者完成了《图解机器学习》这本书的阅读&#xff0c;由于最近深度学习网络大行其是&#xff0c;所以也想要好好的弄清…

【Unity】零基础实现塔防游戏中敌人沿固定路径移动的功能

目录 场景搭建 烘焙(Bake) 敌人动作控制 脚本实现 我们知道&#xff0c;在一些塔防小游戏中&#xff0c;敌人往往会沿着给定的一条路径移动&#xff0c;我们在条路的路边会布置防御设施&#xff0c;攻击消灭敌人&#xff0c;阻止敌人到达终点。 场景搭建 我们首先新建一个…

Leetcode 第 369 场周赛题解

Leetcode 第 369 场周赛题解 Leetcode 第 369 场周赛题解题目1&#xff1a;2917. 找出数组中的 K-or 值思路代码复杂度分析 题目2&#xff1a;2918. 数组的最小相等和思路代码复杂度分析 题目3&#xff1a;2919. 使数组变美的最小增量运算数思路代码复杂度分析 题目4&#xff1…

Git 行结束符:LF will be replaced by CRLF the next time Git touches it问题解决指南

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

ruoyi-vue前端数据字典值引用与回显(列表中回显,多选框回显)

1. 列表中回显&#xff1a; 代码&#xff1a; <el-table v-if"refreshTable" v-loading"loading" :data"deptList" row-key"deptId" :default-expand-all"isExpandAll" :tree-props"{children: children, hasChil…

BP神经网络的数据分类——语音特征信号分类

大家好&#xff0c;我是带我去滑雪&#xff01; BP神经网络&#xff0c;也称为反向传播神经网络&#xff0c;是一种常用于分类和回归任务的人工神经网络&#xff08;ANN&#xff09;类型。它是一种前馈神经网络&#xff0c;通常包括输入层、一个或多个隐藏层和输出层。BP神经网…

虚幻C+++基础 day2

角色移动与视角控制 Character类与相关API 创建Character子类MainPlayer.h // Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h" #include "GameFramework/Character.h" #include &q…

遭受网络攻击泄露了101GB数据

臭名昭著的BlackCat/ALPHV勒索软件团伙声称对另一个组织发起了攻击。今天轮到意大利-法国科西嘉-费里斯公司发现自己正在与勒索软件作斗争。 BlackCat 在其数据泄露网站上报告称&#xff0c;该公司是网络攻击的受害者&#xff0c;并发布了从该公司 IT 基础设施中泄露的一系列样…

javaEE进阶

Cookie 是可以伪造的,比如说学生证是可以伪造的 Session 是不可以伪造的,这是学校系统记录在册的 如何获取 Cookie 我们先用 Servlet 原生的获取 cookie 的方式 我们在浏览器进行访问 但是实际上目前是没有 cookie 的,我们按 F12 进行添加 然后再重新访问,就能在 idea 看到 …

nginx下载安装和日志切割

目录 一、nginx安装配置 1.nginx版本 2.nginx安装配置 3.查看安装后的nginx 4.配置PATH变量 二、日志切割 1.给当前日志文件重命名 2.等待 3.写bash脚本 4.查看日志结果 5.加入crontab定时任务 结语 一、nginx安装配置 1.nginx版本 nginx如今分为商业版&#xff0…

SpringBoot定时任务打成jar 引入到新的项目中后并自动执行

一、springBoot开发定时任务 ①&#xff1a;连接数据库实现新增功能 1. 引入依赖 <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional> </dependency> <dependen…

数据库索引详解

目录 第一章、快速了解索引1.1&#xff09;索引是什么1.2&#xff09;为什么使用索引1.3&#xff09;快速上手创建简单索引 第二章、索引分类2.1&#xff09;按数据结构分类2.1.1&#xff09;树型数据结构的索引①二叉树②B树③B 树&#xff1a;B 树的升级版 2.1.2&#xff09;…