C++二分查找、离线算法:最近的房间

news2024/12/28 20:40:20

作者推荐

利用广度优先或模拟解决米诺骨牌

本文涉及的基础知识点

二分查找算法合集

题目

一个酒店里有 n 个房间,这些房间用二维整数数组 rooms 表示,其中 rooms[i] = [roomIdi, sizei] 表示有一个房间号为 roomIdi 的房间且它的面积为 sizei 。每一个房间号 roomIdi 保证是 独一无二 的。
同时给你 k 个查询,用二维数组 queries 表示,其中 queries[j] = [preferredj, minSizej] 。第 j 个查询的答案是满足如下条件的房间 id :
房间的面积 至少 为 minSizej ,且
abs(id - preferredj) 的值 最小 ,其中 abs(x) 是 x 的绝对值。
如果差的绝对值有 相等 的,选择 最小 的 id 。如果 没有满足条件的房间 ,答案为 -1 。
请你返回长度为 k 的数组 answer ,其中 answer[j] 为第 j 个查询的结果。
示例 1:
输入:rooms = [[2,2],[1,2],[3,2]], queries = [[3,1],[3,3],[5,2]]
输出:[3,-1,3]
解释:查询的答案如下:
查询 [3,1] :房间 3 的面积为 2 ,大于等于 1 ,且号码是最接近 3 的,为 abs(3 - 3) = 0 ,所以答案为 3 。
查询 [3,3] :没有房间的面积至少为 3 ,所以答案为 -1 。
查询 [5,2] :房间 3 的面积为 2 ,大于等于 2 ,且号码是最接近 5 的,为 abs(3 - 5) = 2 ,所以答案为 3 。
示例 2:
输入:rooms = [[1,4],[2,3],[3,5],[4,1],[5,2]], queries = [[2,3],[2,4],[2,5]]
输出:[2,1,3]
解释:查询的答案如下:
查询 [2,3] :房间 2 的面积为 3 ,大于等于 3 ,且号码是最接近的,为 abs(2 - 2) = 0 ,所以答案为 2 。
查询 [2,4] :房间 1 和 3 的面积都至少为 4 ,答案为 1 因为它房间编号更小。
查询 [2,5] :房间 3 是唯一面积大于等于 5 的,所以答案为 3 。
参数范围
n == rooms.length
1 <= n <= 105
k == queries.length
1 <= k <= 104
1 <= roomIdi, preferredj <= 107
1 <= sizei, minSizej <= 107

分析

时间复杂

O(nlogn)。

步骤

一,预处理。房间按面积排序,从大到小。对查询的索引排序,面积大的在前。
二,枚举每个查询,将房间面积大于等于当前查询面积的房间号加到setRoomNO中。在setRoomNO中找第一个大于等于preferredj和小于preferredj的房间号。比较看那个更接近preferredj。

代码

核心代码

class Solution {
public:
	vector<int> closestRoom(vector<vector<int>>& rooms, vector<vector<int>>& queries) {
		vector<int> indexs(queries.size());
		iota(indexs.begin(), indexs.end(), 0);
		sort(indexs.begin(), indexs.end(), [&queries](const int& i1, const int& i2) {return queries[i1][1] > queries[i2][1]; });
		sort(rooms.begin(), rooms.end(), [](const auto& v1, const auto& v2) {return v1[1] > v2[1]; });
		int indexRoom = 0;
		set<int> setRoomNO;
		vector<int> vRet(queries.size(),-1);
		for (const auto& i : indexs)
		{
			while ((indexRoom < rooms.size()) && (rooms[indexRoom][1] >= queries[i][1]))
			{
				setRoomNO.emplace(rooms[indexRoom][0]);
				indexRoom++;
			}
			auto it = setRoomNO.lower_bound(queries[i][0]);
			if ((setRoomNO.end() == it)&&(setRoomNO.begin() == it))
			{
				continue;
			}
			else if (setRoomNO.end() == it)
			{
				vRet[i] = *std::prev(it);
			}
			else if (setRoomNO.begin() == it)
			{
				vRet[i] = *it;
			}
			else
			{
				vRet[i] = (*it - queries[i][0] >= queries[i][0] - *std::prev(it)) ? *std::prev(it) : *it;	
			}
		}
		return vRet;
	}
};

测试用例

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> rooms, queries;
vector res;
{
rooms = { {2,2},{1,2},{3,2} };
queries = { {3,1},{3,3},{5,2} };
Solution slu;
res = slu.closestRoom(rooms, queries);
Assert(res, vector{3, -1, 3});
}
{
rooms = { {1,4},{2,3},{3,5},{4,1},{5,2} };
queries = { {2,3},{2,4},{2,5} };
Solution slu;
res = slu.closestRoom(rooms, queries);
Assert(res, vector{2,1, 3});
}
{
rooms = { {2,2},{1,2},{3,2} };
queries = { {3,1},{3,3},{5,2} };
Solution slu;
res = slu.closestRoom(rooms, queries);
Assert(res, vector{3, -1, 3});
}

//CConsole::Out(res);

}

小的优化:代码简洁,增加可理解性方便排除

旧代码17行:

auto it = setRoomNO.lower_bound(queries[i][0]);
			if ((setRoomNO.end() == it)&&(setRoomNO.begin() == it))
			{
				continue;
			}
			else if (setRoomNO.end() == it)
			{
				vRet[i] = *std::prev(it);
			}
			else if (setRoomNO.begin() == it)
			{
				vRet[i] = *it;
			}
			else
			{
				vRet[i] = (*it - queries[i][0] >= queries[i][0] - *std::prev(it)) ? *std::prev(it) : *it;	
			}

新代码12行

std::map<int, int> mAbsToRoomNO;
			auto it = setRoomNO.lower_bound(queries[i][0]);
			if (setRoomNO.end() != it)
			{
				mAbsToRoomNO[*it - queries[i][0]] = *it;
			}
			if (setRoomNO.begin() != it)
			{
				const auto itPre = std::prev(it);
				mAbsToRoomNO[queries[i][0]- *itPre] = *itPre;
			}
			vRet[i] = (mAbsToRoomNO.size()) ? mAbsToRoomNO.begin()->second : -1;

2023年3月旧代码

class Solution {
public:
vector closestRoom(vector<vector>& rooms, vector<vector>& queries) {
vector indexs;
for (int i = 0; i < queries.size(); i++)
{
indexs.push_back(i);
}
auto SortFun = [](const vector& v1, const vector& v2)
{
return v1[1] < v2[1];
};
std::sort(rooms.begin(), rooms.end(), SortFun);
std::sort(indexs.begin(), indexs.end(), [&queries](const int& i1, const int& i2)
{
return queries[i1][1] < queries[i2][1];
});
std::set setRoomNO;
int j = rooms.size() - 1;
vector vRet(queries.size());
for (int i1 = queries.size() - 1; i1 >= 0; i1–)
{
const int i = indexs[i1];
const auto& vq = queries[i];
while ((j >=0 ) && (rooms[j][1] >= vq[1]))
{
setRoomNO.emplace(rooms[j][0]);
j–;
}
auto it = setRoomNO.lower_bound(vq[0]);
std::set setSelRoomNO;
if (setRoomNO.end() != it)
{
setSelRoomNO.insert(it);
}
if (setRoomNO.begin() != it)
{
setSelRoomNO.insert(
(–it));
}
if (0 == setSelRoomNO.size())
{
vRet[i] = -1;
}
else if (1 == setSelRoomNO.size())
{
vRet[i] = *setSelRoomNO.begin();
}
else if (2 == setSelRoomNO.size())
{
bool bPre = abs(vq[0] - *setSelRoomNO.begin()) <= abs(vq[0] - *setSelRoomNO.rbegin());
vRet[i] = bPre ? *setSelRoomNO.begin() : *setSelRoomNO.rbegin() ;
}
}
return vRet;
}
};

扩展阅读

视频课程

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

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

相关文章

基于SSM的云鑫曦科技办公自动化管理系统设计与实现

基于SSM的云鑫曦科技办公自动化管理系统设计与实现 摘 要: 随着时代的发展&#xff0c;单位办公方式逐渐从传统的线下纸张办公转向了使用个人pc的线上办公&#xff0c;办公效率低下的传统纸质化办公时代的淘汰&#xff0c;转型到信息化办公时代&#xff0c;面对当今数据逐渐膨…

上海亚商投顾:沪指震荡反弹 汽车产业链掀涨停潮

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 三大指数昨日震荡反弹&#xff0c;北证50指数跌超4%&#xff0c;近50只北交所个股跌超10%。 新能源车产业链掀…

探索短剧市场的商机:打造短视频平台的全方位指南

目前短剧市场蓬勃发展&#xff0c;上半年备案数远超电视剧&#xff0c;彰显了短剧小程序市场潜力巨大&#xff0c;商业价值巨大。用户对短小精悍娱乐内容的需求不断增加&#xff0c;而新兴市场中有限的短剧小程序正好能够迎合这一需求。 搭建短视频平台的关键步骤&#xff1a; …

Postgres 数据库中 ULID 和 UUID 的性能

大家好&#xff01;在本文中&#xff0c;我想分享我对经常用作标识符的数据类型的知识和看法。今天我们将同时讨论两个主题。这些是数据库端按键和键的数据类型衡量的搜索速度。 我将使用PostgreSQL数据库和演示Java服务来比较查询速度。 UUID 和 ULID 为什么我们需要某种难…

MyBatis使用教程详解<下>

回顾上一篇博文,我们讲了如何使用注解/XML的方式来操作数据库,实际上,一个Mapper接口的实现,这两种方式是可以并存的. 上一篇博文中,我们演示的都是比较简单的SQL语句,没有设计到复杂的逻辑,本篇博文会讲解复杂SQL的实现及一些细节处理.话不多说,让我们开始吧. 一. #{}和${} …

基于LNMP快速搭建WordPress平台

目录 1 LNMP简介 2 WordPress简介 3 安装MySQL环境 3.1 安装MySQL 3.1.1 下载wget工具 3.1.2 下载MySQL官方yum源安装包 3.1.3 安装MySQL官方yum源 3.1.4 mysql安装 3.2 启动MySQL 3.3 获取默认密码 3.4 登录MySQL ​ 3.5 修改密码 3.6 创建WordPress数据库并授权 3.6.1 创…

5 时间序列预测入门:LSTM+Transformer

0 引言 论文地址&#xff1a;https://arxiv.org/abs/1706.03762 1 Transformer Transformer 模型是一种用于处理序列数据的深度学习模型&#xff0c;主要用于解决自然语言处理&#xff08;NLP&#xff09;任务。它在许多 NLP 任务中取得了重大突破&#xff0c;如机器翻译、文本…

微服务实战系列之Cache

前言 欢迎来到Cache&#xff08;缓存&#xff09;的世界&#xff01; 自从世界第一台计算机诞生之日起&#xff0c;人们对效率的渴望逐步增强。从CPU到存储&#xff0c;从芯片到内存&#xff0c;一批又一批的先驱以一种孜孜不倦的“工匠”精神&#xff0c;为计算机运行效率的提…

【数据结构 —— 二叉树的链式结构实现】

数据结构 —— 二叉树的链式结构实现 1.树的概念及其结构1.1.树概念1.2.树的结构1.3树的相关概念1.4.树的表示1.5. 树在实际中的运用&#xff08;表示文件系统的目录树结构&#xff09; 2.二叉树的概念及其结构2.1二叉树的概念2.2.现实中的二叉树&#xff1a;2.3. 特殊的二叉树…

Flutter开发type ‘Future<int>‘ is not a subtype of type ‘int‘ in type cast错误

文章目录 问题描述错误源码 问题分析解决方法修改后的代码 问题描述 今天有个同事调试flutter程序时报错&#xff0c;问我怎么解决&#xff0c;程序运行时报如下错误&#xff1a; type ‘Future’ is not a subtype of type ‘int’ in type cast 错误源码 int order Databas…

FFmpeg介绍

官方网站&#xff1a;http://www.ffmpeg.org/ 项目组成 libavformat 封装模块&#xff0c;封装了Protocol层和Demuxer、Muxer层&#xff0c;使得协议和格式对于开发者来说是透明的。FFmpeg能否支持一种封装格式的视频的封装与解封装&#xff0c;完全取决于这个库&#xff0c…

《微信小程序开发从入门到实战》学习三十五

4.2 云开发JSON数据库 4.2.3 权限控制 在云开发控制台可以对数据库中的数据进行操作&#xff0c; 在小程序端和云函数可以分别使用小程序API和服务端API对数据中的数据进行操作。 以上操作受到权限控制。 对数据库进行查询属于读操作&#xff0c;增删改操作属于写操作。 …

Python自动化办公:PDF文件的加密与解密

在本篇文章中&#xff0c;我们将介绍如何使用PyPDF2库对PDF文件进行加密和解密操作。 包括如何给PDF文件添加密码&#xff0c;以及如何从受密码保护的PDF文件中删除密码。 注&#xff1a;删除密码的操作&#xff0c;前提是需要知道密码哦 1. 安装PyPDF2库 首先&#xff0c;…

【小黑嵌入式系统第十课】μC/OS-III概况——实时操作系统的特点、基本概念(内核任务中断)、与硬件的关系实现

文章目录 一、为什么要学习μC/OS-III二、嵌入式操作系统的发展历史三、实时操作系统的特点四、基本概念1. 前后台系统2. 操作系统3. 实时操作系统&#xff08;RTOS&#xff09;4. 内核5. 任务6. 任务优先级7. 任务切换8. 调度9. 非抢占式&#xff08;合作式&#xff09;内核10…

el-table,列表合并,根据名称列名称相同的品名将其它列值相同的进行合并

el-table,列表合并,根据名称列名称相同的品名讲其它列值相同的进行合并,并且不能垮品名合并 如图 用到el-table合并行的方法合并 tableSpanMethod({ row, column, rowIndex, columnIndex }) {if (column.property "materielName") {//合并商品名const _row this…

CI/CD 构建中能保护好 SSHKEY吗?

目录 背景 方案 编码存储 逐行存储 合并存储 打马赛克 结论 背景 使用极狐GitLab CI/CD&#xff0c;在部署方面&#xff0c;主要有两种方式&#xff1a; 部署到K8S集群 Push模式&#xff1a;流水线通过kubectl执行命令部署&#xff0c;这需要把K8S的权限给流水线&#xf…

【python程序】把小于10的数值都变成1

【python程序】把小于10的数值都变成1 import numpy as np import xarray as xra xr.DataArray(np.arange(25).reshape(5, 5)) a[np.where(a < 10)] 1 print(a)

微信小程序+中草药分类+爬虫+torch

1 介绍 本项目提供中草药数据集&#xff0c;使用gpu、cpu版本的torch版本进行训练&#xff0c;将模型部署到后端flask&#xff0c;最后使用微信小程序进行展示出来。 数据爬虫可以参考&#xff1a;http://t.csdnimg.cn/7Olus 项目中的爬虫代码&#xff0c;并且本项目提供相同的…

拆解按摩器:有意思的按键与LED控制电路,学习借鉴一下!

拆解 外观和配色个人感觉还行,比较青春 拉开拉链&#xff0c;拆开外面的布面&#xff0c;里面还有一层纱面 按键部分使用魔术贴固定 拆开纱面后&#xff0c;看到里面的结构&#xff0c;整体是一个海绵 可以看到如下&#xff0c;电池&#xff0c;按键板&#xff0c;充电线的三条…

匿名内部类(内部类) - Java

匿名内部类 1、理解2、语法3、使用&#xff08;1&#xff09;基于接口的内部类&#xff08;2&#xff09;基于类的内部类&#xff08;3&#xff09;基于抽象类的匿名内部类 4、细节&注意事项5、最佳应用场景&#xff08;1&#xff09;当作实参直接传递&#xff0c;简洁高效…