当前位置: 首页 > news >正文

【二分查找】LeetCode1970:你能穿过矩阵的最后一天

本文涉及的基础知识点

二分查找算法合集

作者推荐

动态规划LeetCode2552:优化了6版的1324模式

题目

给你一个下标从 1 开始的二进制矩阵,其中 0 表示陆地,1 表示水域。同时给你 row 和 col 分别表示矩阵中行和列的数目。

一开始在第 0 天,整个 矩阵都是 陆地 。但每一天都会有一块新陆地被 水 淹没变成水域。给你一个下标从 1 开始的二维数组 cells ,其中 cells[i] = [ri, ci] 表示在第 i 天,第 ri 行 ci 列(下标都是从 1 开始)的陆地会变成 水域 (也就是 0 变成 1 )。

你想知道从矩阵最 上面 一行走到最 下面 一行,且只经过陆地格子的 最后一天 是哪一天。你可以从最上面一行的 任意 格子出发,到达最下面一行的 任意 格子。你只能沿着 四个 基本方向移动(也就是上下左右)。
请返回只经过陆地格子能从最 上面 一行走到最 下面 一行的 最后一天 。
示例 1:
输入:row = 2, col = 2, cells = [[1,1],[2,1],[1,2],[2,2]]
输出:2
解释:上图描述了矩阵从第 0 天开始是如何变化的。
可以从最上面一行到最下面一行的最后一天是第 2 天。
示例 2:
输入:row = 2, col = 2, cells = [[1,1],[1,2],[2,1],[2,2]]
输出:1
解释:上图描述了矩阵从第 0 天开始是如何变化的。
可以从最上面一行到最下面一行的最后一天是第 1 天。
示例 3:
输入:row = 3, col = 3, cells = [[1,2],[2,1],[3,3],[2,2],[1,1],[1,3],[2,3],[3,2],[3,1]]
输出:3
解释:上图描述了矩阵从第 0 天开始是如何变化的。
可以从最上面一行到最下面一行的最后一天是第 3 天。
参数范围
2 <= row, col <= 2 * 104
4 <= row * col <= 2 * 104
cells.length == row * col
1 <= ri <= row
1 <= ci <= col
cells 中的所有格子坐标都是 唯一 的。

二分查找分析

时间复杂度

O(nlogn) ,二分查找O(logn),并集查找O(n)。

分析

随着天数的增大,逐步从能过变成不能过。左闭右开空间。
并集查找的时候只需要连接左边和上边。第一行下移,就是第二行上移。

代码

核心代码

class Solution {
public:
int latestDayToCross(int row, int col, vector<vector>& cells) {
m_r = row;
m_c = col;
int left = 0, right = m_r * m_c ;
while (right - left > 1)
{
const auto mid = left + (right - left) / 2;
vector<vector> mat(row, vector(col));
for (int i = 0; i < mid; i++)
{
mat[cells[i][0]-1][cells[i][1]-1] = 1;
}
if (Can(mat))
{
left = mid;
}
else
{
right = mid;
}
}
return left;
}
bool Can(const vector<vector>& mat)
{
const int n = m_r*m_c;
CUnionFind uf(n + 2);
for (int r = 0; r < m_r; r++)
{
for (int c = 0; c < m_c; c++)
{
if (1 == mat[r][c])
{
continue;
}
if ((0 != r) && (0 == mat[r - 1][c]))
{
uf.Union(r * m_c + c, (r - 1) * m_c + c);
}
if ((0 != c) && (0 == mat[r][c - 1]))
{
uf.Union(r * m_c + c, r * m_c + c - 1);
}
}
}
for (int c = 0; c < m_c; c++)
{
if (0 == mat[0][c])
{
uf.Union(n, c);
}
if (0 == mat[m_r - 1][c])
{
uf.Union(n+1, (m_r - 1) * m_c + c);
}
}
return uf.IsConnect(n, n + 1);
}
int m_r,m_c;
};

测试用例

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]);
}
}

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

int main()
{
int row, col, res;
vector<vector> cells;
{
row = 2, col = 2, cells = { {1,1},{2,1},{1,2},{2,2} };
Solution slu;
auto res = slu.latestDayToCross(row, col, cells);
Assert(2, res);
}
{
row = 2, col = 2, cells = { {1,1},{1,2},{2,1},{2,2} };
Solution slu;
auto res = slu.latestDayToCross(row, col, cells);
Assert(1, res);
}
{
row = 6, col = 2, cells = { {4, 2}, { 6,2 }, { 2,1 }, { 4,1 }, { 6,1 }, { 3,1 }, { 2,2 }, { 3,2 }, { 1,1 }, { 5,1 }, { 5,2 }, { 1,2 } };
Solution slu;
auto res = slu.latestDayToCross(row, col, cells);
Assert(3, res);
}

  //CConsole::Out(res);

}

逆序思考

反向思考:水慢慢变成陆地,最晚什么时候连通陆地。
时间复杂度😮(n)

代码

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<int> GetNodeCountOfRegion()//各联通区域的节点数量{const int iNodeSize = m_vNodeToRegion.size();vector<int> vRet(iNodeSize);for (int i = 0; i < iNodeSize; i++){vRet[GetConnectRegionIndex(i)]++;}return vRet;}std::unordered_map<int, vector<int>> GetNodeOfRegion(){std::unordered_map<int, vector<int>> 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<int> m_vNodeToRegion;//各点所在联通区域的索引,本联通区域任意一点的索引,为了增加可理解性,用最小索引int m_iConnetRegionCount;
};class Solution {
public:int latestDayToCross(int row, int col, vector<vector<int>>& cells) {m_r = row;m_c = col;const int n = m_r * m_c;CUnionFind uf(n + 2);for (int c = 0; c < m_c; c++){uf.Union(n, c);uf.Union(n + 1, (m_r - 1) * m_c + c);}vector<vector<int>> mat(row, vector<int>(col,1));for (int i = cells.size() - 1; i >= 0; i--){const int r = cells[i][0] - 1;const int c = cells[i][1] - 1;mat[r][c] = 0;auto Add = [&](const int rNew, const int cNew){if ((rNew < 0) || (rNew >= m_r)){return;}if ((cNew < 0) || (cNew >= m_c)){return;}if (0 == mat[rNew][cNew]){uf.Union(r * m_c + c, rNew * m_c + cNew);}};Add(r + 1, c);Add(r - 1, c);Add(r, c - 1);Add(r, c + 1);if (uf.IsConnect(n, n + 1)){return i ;}}		return 0;}int m_r,m_c;
};

2023年3月旧代码

class Solution {
public:
int latestDayToCross(int row, int col, vector<vector>& cells) {
m_r = row;
m_c = col;
int left = 0,r = cells.size()+1 ;
while (r > left + 1)
{
int iMid = left + (r - left) / 2;
vector<vector> mat(m_r, vector(m_c));
for (int i = 0; i < iMid; i++)
{
mat[cells[i][0]-1][cells[i][1]-1] = 1;
}
if (bfs(mat))
{
left = iMid;
}
else
{
r = iMid;
}
}
return left;
}
bool bfs(const vector<vector>& mat)
{
std::queue<std::pair<int, int>> queCanViste;
std::unordered_map<int, std::unordered_set> setDo;
for (int c = 0; c < m_c; c++)
{
Add(queCanViste, setDo, 0, c, mat);
}
while (queCanViste.size())
{
const int r = queCanViste.front().first;
const int c = queCanViste.front().second;
if (r == m_r - 1)
{
return true;
}
queCanViste.pop();
Add(queCanViste, setDo, r+1, c, mat);
Add(queCanViste, setDo, r-1, c, mat);
Add(queCanViste, setDo, r , c+1, mat);
Add(queCanViste, setDo, r, c-1, mat);
}
return false;
}
void Add(std::queue<std::pair<int, int>>& queCanViste, std::unordered_map<int, std::unordered_set>& setDo, int r, int c,const vector<vector>& mat)
{
if ((r < 0) || (r >= m_r))
{
return;
}
if ((c<0) || (c >=m_c))
{
return;
}
if (1 == mat[r][c])
{
return;
}
if (setDo[r].count©)
{
return;
}
queCanViste.emplace(r, c);
setDo[r].emplace©;
}
int m_r, m_c;
};

2023年9月旧代码

class Solution {
public:
int latestDayToCross(int row, int col, vector<vector>& cells) {
m_c = col;
int iMaskNum = row * col;
vector<vector> grid(row, vector(col));
for (auto& v : cells)
{
v[0]–;
v[1]–;
grid[v[0]][v[1]] = 1;
}
CUnionFind uf(iMaskNum+2);//增加两个特殊端点; iMaskNum 连接所有第0行 iMaskNum+1 连接多有最后一行
auto Add = [&row,this,&grid,&uf](int iMask, int r, int c)
{
if ((r < 0) || (r >= row))
{
return;
}
if ((c < 0) || (c >= m_c))
{
return;
}
if (1 == grid[r][c])
{
return;
}
uf.Union(iMask, Mask(r, c));
};
for (int r = 0; r < row; r++)
{
for (int c = 0; c < m_c; c++)
{
if (1 == grid[r][c])
{
continue;
}
const int mask = Mask(r, c);
Add(mask, r + 1, c);
Add(mask, r, c + 1);
}
}
for (int c = 0; c < m_c; c++)
{
uf.Union(iMaskNum, Mask(0, c));
uf.Union(iMaskNum+1, Mask(row-1, c));
}
for (int i = cells.size() - 1; i >= 0; i–)
{
if (uf.IsConnect(iMaskNum, iMaskNum+1))
{
return i+1;
}
const auto& v = cells[i];
grid[v[0]][v[1]] = 0;
const int mask = Mask(v[0], v[1]);
Add(mask, v[0] + 1, v[1]);
Add(mask, v[0], v[1] + 1);
Add(mask, v[0] - 1, v[1]);
Add(mask, v[0], v[1] - 1);
}
return 0;
}
inline int Mask(int r, int c)
{
return r * m_c + c;
}
int 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

相关文章:

【二分查找】LeetCode1970:你能穿过矩阵的最后一天

本文涉及的基础知识点 二分查找算法合集 作者推荐 动态规划LeetCode2552&#xff1a;优化了6版的1324模式 题目 给你一个下标从 1 开始的二进制矩阵&#xff0c;其中 0 表示陆地&#xff0c;1 表示水域。同时给你 row 和 col 分别表示矩阵中行和列的数目。 一开始在第 0 …...

利用python连接MySQL数据库并执行相关sql操作

一、新建MySQL数据库 1.启动MySQL服务 打开phpstudy&#xff0c;开启MySQL服务。如果开启失败的话&#xff0c;可以打开任务管理器&#xff0c;把正在运行的mysqld服务的进程进行关闭&#xff0c;再次打开MySQL服务即可启动。 2.新建MySQL数据库 选择数据库&#xff0c;点击…...

jenkins配置

branch: "dev" 切换分支 $WORKSPACE&#xff1a; /var/lib/jenkins/workspace/jenkins任务名 dest_passwd服务器密码 变量 sudo sshpass -p $dest_passwd ssh root192.168.211.319 -tt rm -rf /data/patent/*&#xff1a;删除文件/data/patent/* sudo sshpa…...

LeNet对MNIST 数据集中的图像进行分类--keras实现

我们将训练一个卷积神经网络来对 MNIST 数据库中的图像进行分类&#xff0c;可以与前面所提到的CNN实现对比CNN对 MNIST 数据库中的图像进行分类-CSDN博客 加载 MNIST 数据库 MNIST 是机器学习领域最著名的数据集之一。 它有 70,000 张手写数字图像 - 下载非常简单 - 图像尺…...

Django的回顾的第4天

1.模型层 1.1简介 你可能已经注意到我们在例子视图中返回文本的方式有点特别。 也就是说&#xff0c;HTML被直接硬编码在 Python代码之中。 def current_datetime(request):now datetime.datetime.now()html "<html><body>It is now %s.</body><…...

点云从入门到精通技术详解100篇-基于三维点云的工件曲面轮廓检测与机器人打磨轨迹规划(中)

目录 2.2.2 散乱点云滤波去噪 2.2.3 海量点云数据压缩 2.3 点云采集与预处理实验...

Mapper文件夹在resource目录下但是网页报错找不到productMapper.xml文件的解决

报错如下&#xff1a; 我的Mapper文件夹在resourse目录下但是网页报错找不到productMapper.xml。 结构如下&#xff1a;代码如下&#xff1a;<mappers><mapper resource"com/dhu/mapper/productMapper.xml" /> </mappers> 这段代码是在mybatis-co…...

22.Oracle中的临时表空间

Oracle中的临时表空间 一、临时表空间概述1、什么是临时表空间2、临时表空间的作用 二、临时表空间相关语法三、具体使用案例1、具体使用场景示例2、具体使用场景代码示例 点击此处跳转下一节&#xff1a;23.Oracle11g的UNDO表空间点击此处跳转上一节&#xff1a;21.Oracle的程…...

附录A 指令集基本原理

1. 引言 本书主要关注指令集体系结构4个主题&#xff1a; 1. 提出对指令集进行分类的方法&#xff0c;并对各种方法的优缺点进行定性评估&#xff1b; 2. 提出并分析一些在很大程度上独立于特定指令集的指令集评估数据。 3. 讨论语言与编译器议题以及…...

Unittest单元测试之unittest用例执行顺序

unittest用例执行顺序 当在一个测试类或多个测试模块下&#xff0c;用例数量较多时&#xff0c;unittest在执行用例 &#xff08;test_xxx&#xff09;时&#xff0c;并不是按从上到下的顺序执行&#xff0c;有特定的顺序。 unittest框架默认根据ACSII码的顺序加载测试用例&a…...

海云安谢朝海:开发安全领域大模型新实践 人工智能助力高效安全左移

2023年11月29日&#xff0c;2023中国&#xff08;深圳&#xff09;金融科技大会成功举行&#xff0c;该会议是深圳连续举办的第七届金融科技主题年度会议&#xff0c;也是2023深圳国际金融科技节重要活动之一。做好金融工作&#xff0c;需要兼顾创新与安全&#xff0c;当智能体…...

Postman接口测试工具完整教程

前言 作为软件开发过程中一个非常重要的环节&#xff0c;软件测试越来越成为软件开发商和用户关注的焦点。完善的测试是软件质量的保证&#xff0c;因此软件测试就成了一项重要而艰巨的工作。要做好这项工作当然也绝非易事。 第一部分&#xff1a;基础篇 postman:4.5.1 1.安…...

Android 滑动按钮(开关) SwitchCompat 自定义风格

原生的SwitchCompat控件如下图&#xff0c;不说不堪入目&#xff0c;也算是不敢恭维了。开个玩笑... 所以我们就需要对SwitchCompat进行自定义风格&#xff0c;效果如下图 代码如下 <androidx.appcompat.widget.SwitchCompatandroid:id"id/switch_compat"android:…...

前端面试灵魂提问-计网(2)

1、websocket 为什么全双工? 1.1 WebSocket是什么 WebSocket 是一种通信协议&#xff0c;它在客户端和服务器之间建立持久的全双工连接。全双工意味着数据可以双向流动&#xff0c;即客户端可以向服务器发送消息&#xff0c;服务器也可以向客户端发送消息&#xff0c;而无需…...

Git修改远程仓库名称

1、先直接在远程点仓库名&#xff0c;然后左侧菜单栏找settings-general&#xff0c;然后直接修改工程名&#xff0c;保存即可。 2、还是在settings-general下&#xff0c;下拉找到Advanced点击Expand展开&#xff0c;然后下拉到最底部 在Change path里填入新的项目名称&#x…...

kafka 集群 ZooKeeper 模式搭建

Apache Kafka是一个开源分布式事件流平台&#xff0c;被数千家公司用于高性能数据管道、流分析、数据集成和关键任务应用程序 Kafka 官网&#xff1a;Apache Kafka 关于ZooKeeper的弃用 根据 Kafka官网信息&#xff0c;随着Apache Kafka 3.5版本的发布&#xff0c;Zookeeper现…...

【LeetCode】 160. 相交链表

相交链表 题目题解 题目 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。 图示两个链表在节点 c1 开始相交&#xff1a; 题目数据 保证 整个链式结构中不存在环。 注意&am…...

TZOJ 1429 小明A+B

答案&#xff1a; #include <stdio.h> int main() {int T0, A0, B0, sum0;scanf("%d", &T); //输入测试数据的组数while (T--) //循环T次{scanf("%d %d", &A, &B); //输入AB的值sum A B;if (sum > 100) //如果是三位数{…...

制作openeuler的livecd

下载该项目&#xff0c;执行下面的操作gitee openeuler livecd项目 基于openeuler环境 #安装工具&#xff0c;第一次可能报错&#xff0c;可以再执行一次 make installx86 livecd-creator -d -v --config./config/euler_x86_64.ks --fslabeleuler-LiveCD --cachecache --log…...

B.牛牛排队伍——模拟双链表

当前位置: 首页 > news >正文 B.牛牛排队伍——模拟双链表 news 2023/12/1 15:14:37 分析 题目其实很简单,就是双链表的增删查,但是刚开始,直接vis标记删除元素,查找一个位置的前一个用的while不断向前找,但是TLE;毕竟O(n*k)的复杂度,一开始没有考虑时间复杂度…...

【网络安全产品大调研系列】2. 体验漏洞扫描

前言 2023 年漏洞扫描服务市场规模预计为 3.06&#xff08;十亿美元&#xff09;。漏洞扫描服务市场行业预计将从 2024 年的 3.48&#xff08;十亿美元&#xff09;增长到 2032 年的 9.54&#xff08;十亿美元&#xff09;。预测期内漏洞扫描服务市场 CAGR&#xff08;增长率&…...

渲染学进阶内容——模型

最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

(转)什么是DockerCompose?它有什么作用?

一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用&#xff0c;而无需手动一个个创建和运行容器。 Compose文件是一个文本文件&#xff0c;通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

Rapidio门铃消息FIFO溢出机制

关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系&#xff0c;以下是深入解析&#xff1a; 门铃FIFO溢出的本质 在RapidIO系统中&#xff0c;门铃消息FIFO是硬件控制器内部的缓冲区&#xff0c;用于临时存储接收到的门铃消息&#xff08;Doorbell Message&#xff09;。…...

中医有效性探讨

文章目录 西医是如何发展到以生物化学为药理基础的现代医学&#xff1f;传统医学奠基期&#xff08;远古 - 17 世纪&#xff09;近代医学转型期&#xff08;17 世纪 - 19 世纪末&#xff09;​现代医学成熟期&#xff08;20世纪至今&#xff09; 中医的源远流长和一脉相承远古至…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA

浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求&#xff0c;本次涉及的主要是收费汇聚交换机的配置&#xff0c;浪潮网络设备在高速项目很少&#xff0c;通…...

基于Java+VUE+MariaDB实现(Web)仿小米商城

仿小米商城 环境安装 nodejs maven JDK11 运行 mvn clean install -DskipTestscd adminmvn spring-boot:runcd ../webmvn spring-boot:runcd ../xiaomi-store-admin-vuenpm installnpm run servecd ../xiaomi-store-vuenpm installnpm run serve 注意&#xff1a;运行前…...

如何配置一个sql server使得其它用户可以通过excel odbc获取数据

要让其他用户通过 Excel 使用 ODBC 连接到 SQL Server 获取数据&#xff0c;你需要完成以下配置步骤&#xff1a; ✅ 一、在 SQL Server 端配置&#xff08;服务器设置&#xff09; 1. 启用 TCP/IP 协议 打开 “SQL Server 配置管理器”。导航到&#xff1a;SQL Server 网络配…...

uni-app学习笔记三十五--扩展组件的安装和使用

由于内置组件不能满足日常开发需要&#xff0c;uniapp官方也提供了众多的扩展组件供我们使用。由于不是内置组件&#xff0c;需要安装才能使用。 一、安装扩展插件 安装方法&#xff1a; 1.访问uniapp官方文档组件部分&#xff1a;组件使用的入门教程 | uni-app官网 点击左侧…...