C++二分查找算法的应用:俄罗斯套娃信封问题

本文涉及的基础知识点

二分查找

题目

给你一个二维整数数组 envelopes ,其中 envelopes[i] = [wi, hi] ,表示第 i 个信封的宽度和高度。
当另一个信封的宽度和高度都比这个信封大的时候,这个信封就可以放进另一个信封里,如同俄罗斯套娃一样。
请计算 最多能有多少个 信封能组成一组“俄罗斯套娃”信封(即可以把一个信封放到另一个信封里面)。
注意:不允许旋转信封。
示例 1:
输入:envelopes = [[5,4],[6,4],[6,7],[2,3]]
输出:3
解释:最多信封的个数为 3, 组合为: [2,3] => [5,4] => [6,7]。
示例 2:
输入:envelopes = [[1,1],[1,1],[1,1]]
输出:1
参数提示
1 <= envelopes.length <= 105
envelopes[i].length == 2
1 <= wi, hi <= 105

超时解法

有两个地方可能超时:
一,std::map<int, int> dp = mPreYToNum;
二,for (; (ij != dp.end()) && (ij->second > len); ++ij);
一处的时间复杂度是:O(n),最多有n个元素,所以总时间复杂度是O(n*n),会引起超时。
二处,总时间复杂度是O(n),最多删除n次,每个元素最多只会被删除一次。

代码

class Solution {
public:
int maxEnvelopes(vector<vector>& envelopes) {
std::map<int, vector> mXToYS;
for (const auto& v : envelopes)
{
mXToYS[v[0]].emplace_back(v[1]);
}
std::map<int, int> mPreYToNum;//y值对应最大数量,y值越大,对应的数量越大,否则被淘汰了
int iMax = 0;
for (const auto& it : mXToYS)
{
std::map<int, int> dp = mPreYToNum;
for (const auto& y : it.second)
{
int len = 0;
{//计算长度
const auto it = mPreYToNum.lower_bound(y);
len = 1 + ((mPreYToNum.begin() == it) ? 0 : std::prev(it)->second);
iMax = max(iMax, len);
}
{
const auto it = dp.lower_bound(y);
auto ij = it;
for (; (ij != dp.end()) && (ij->second > len); ++ij);
dp.erase(it, ij);
if (!dp.count(y))
{
dp[y] = len;
}
}
}
mPreYToNum.swap(dp);
}

	return iMax;
}

};

测试用例

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()
{
Solution slu;
vector<vector> envelopes;
int res = 0;
envelopes = { {5,4},{6,4},{6,7},{2,3} };
res = slu.maxEnvelopes(envelopes);
Assert(res, 3);
envelopes = { {1,1},{1,1},{1,1} };
res = slu.maxEnvelopes(envelopes);
Assert(res, 1);
envelopes = { {1,1},{2,2},{2,3} };
res = slu.maxEnvelopes(envelopes);
Assert(res, 2);
envelopes = { {1,2},{2,3},{3,4},{3,5},{4,5},{5,5},{5,6},{6,7},{7,8} };
res = slu.maxEnvelopes(envelopes);
Assert(res, 7);

//CConsole::Out(res);

}

正确解法

变量含义

mXToYSkey为envelopes的x,值为envelopes的y
mYToNum[x取[0,x), y对应最大套娃数量
vector<pair<int, int>> vYNum当前x,各y对应数量

注意:

x相同,无法套娃,所以必须等当前x处理完毕,才能更新mYToNum。
y值越大,对应的数量越大,否则被淘汰了。所以mYToNum的键和值都是升序。
y小于当前y的,不会淘汰当前y,因为当前长度就是小于y的最大长度+1。
所以只会被相等的y淘汰。
当前y 可能淘汰比当前y大的。

代码

class Solution {
public:
int maxEnvelopes(vector<vector>& envelopes) {
std::map<int, vector> mXToYS;
for (const auto& v : envelopes)
{
mXToYS[v[0]].emplace_back(v[1]);
}
std::map<int, int> mYToNum;//y值对应最大数量
int iMax = 0;
for (const auto& it : mXToYS)
{
vector<pair<int, int>> vYNum;
for (const auto& y : it.second)
{
const auto it = mYToNum.lower_bound(y);
const int num = 1 + ((mYToNum.begin() == it) ? 0 : std::prev(it)->second);
iMax = max(iMax, num);
vYNum.emplace_back(y, num);
}
for(const auto[y,num]: vYNum)
{
const auto it = mYToNum.lower_bound(y);
auto ij = it;
for (; (ij != mYToNum.end()) && (ij->second <= num); ++ij);
mYToNum.erase(it, ij);
if (!mYToNum.count(y))
{
mYToNum[y] = num;
}
}
}
return iMax;
}
};

2023年1月旧代码

class Solution {
public:
int maxEnvelopes(vector<vector>& envelopes) {
std::map<int, vector> mWidthToHeights;
for (const auto& v : envelopes)
{
mWidthToHeights[v[0]].push_back(v[1]);
}
int iMax = 1;
std::map<int, int> mHeightNum;
for ( auto& it : mWidthToHeights)
{
sort(it.second.begin(), it.second.end(),std::greater());
for (auto& height : it.second)
{
auto it = mHeightNum.lower_bound(height);
int iNum =1;
if (mHeightNum.begin() != it)
{//没有套
auto ij = it;
–ij;
iNum = ij->second + 1;
}
iNum = max(iNum,mHeightNum[height]);
auto ij = it;
while ( (ij != mHeightNum.end())&& ( ij->second < iNum))
{
ij++;
}
mHeightNum.erase(it, ij);
mHeightNum[height] = max(mHeightNum[height], iNum);
iMax = max(iMax, mHeightNum[height]);
}
}
return iMax;
}
};

扩展阅读

视频课程

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

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

相关文章

2023年是5G-A标准制定关键年 华为实现5G-A重大突破

5G商用四年&#xff0c;2023年5G应用项目已经达到10万个&#xff0c;5G向千行百业渗透的同时&#xff0c;也在向5G-Advanced&#xff08;下简称5G-A&#xff09;演进。 10月20日&#xff0c;在工业和信息化部主办的2023年中国5G发展大会上&#xff0c;由IMT-2020&#xff08;5G…

【chatglm3】(2)使用docker运行chatglm3对外的http服务,使用python代码执行函数调用,查询北京天气

函数调用的演示视频&#xff1a; 使用docker运行最新chatglm3-6b&#xff0c;对外的http服务&#xff0c;使用python代码执行函数调用&#xff0c;查询北京天气代码演示和说明 使用docker运行最新chatglm3-6b&#xff0c;对外的http服务&#xff0c;使用python代码执行函数调用…

unraid 安装并设置 zerotier 内网穿透安装 unraid 局域网内其他设备

Read Original 最近看了以下两个文章&#xff0c;感谢发布的各种精彩文章&#xff0c;让我受益匪浅。OPENWRT 的固件在设置了&#xff0c;【自动允许客户端 NAT】后&#xff0c;可以直接访问局域网其他设备&#xff0c;而我 unraid 部署 zerotier 后&#xff0c;只能访问 unra…

R语言在生态环境领域中的实践技术应用

R语言作为新兴的统计软件&#xff0c;以开源、自由、免费等特点风靡全球。生态环境领域研究内容广泛&#xff0c;数据常多样而复杂。利用R语言进行多元统计分析&#xff0c;从复杂的现象中发现规律、探索机制正是R的优势。为此&#xff0c;以鱼类、昆虫、水文、地形等多样化的生…

java 数据结构 ArrayList源码底层 LinkedList 底层源码 迭代器底层

文章目录 数据结构总结ArrayList源码底层LinkedList底层源码 迭代器底层 数据结构 对于数据结构我这边只告诉你右边框框里的 栈的特点:后进先出,先进后出,入栈也成为压栈,出栈也成为弹栈 栈就像一个弹夹 队列先进先出后进后出 队列像排队 链表查询满 但是增删快(相对于数组而…

你没有见过的 git log 风格

背景 git大家都不陌生&#xff0c;git log 也是大家经常用的指令&#xff0c;今天分享三种 git log的美化格式&#xff0c;大家看看哪种更易读。 git log -15 --graph --decorate --oneline 带有 pretty 格式的git log 风格 log --color --graph --prettyformat:‘%Cred%h%C…

我在Vscode学OpenCV 处理图像

既然我们是面向Python的OpenCV&#xff08;OpenCV for Python&#xff09;那我们就必须要熟悉Numpy这个库&#xff0c;尤其是其中的数组的库&#xff0c;Python是没有数组的&#xff0c;唯有借助他库才有所实现想要的目的。 # 老三样库--事先导入 import numpy as np import c…

最新 IntelliJ IDEA 旗舰版和社区版下载安装教程(图解)

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

从瀑布模式到水母模式:ChatGPT引领软件研发的革新之路

ChatGPT引领软件研发的革新之路 概述操作建议本书优势 内容简介作者简介专家推荐读者对象目录直播预告写在末尾&#xff1a; 主页传送门&#xff1a;&#x1f4c0; 传送 概述 计算机技术的发展和互联网的普及&#xff0c;使信息处理和传输变得更加高效&#xff0c;极大地改变了…

SSL数字证书服务

SSL/TLS 证书允许Web浏览器使用安全套接字层/传输层安全 (SSL/TLS) 协议识别并建立与网站的加密网络连接。 SSL数字证书主要功能 SSL证书在浏览器或用户计算机与服务器或网站之间建立加密连接。这种连接可以保护传输中的敏感数据免遭非授权方的拦截&#xff0c;从而使在线交易…

如何记录每天的工作日程?电脑手机通用的日程管理软件

在工作时间有限&#xff0c;但工作任务愈加繁多的现在职场中&#xff0c;要求每一个职场人士做好高效日程管理。通过高效管理日程&#xff0c;我们可以更好地组织和安排任务&#xff0c;合理分配时间和优先级&#xff0c;这有助于我们更专注地进行工作&#xff0c;减少时间的浪…

每个外贸人都有一颗不甘的心

是不是每个三十多岁的外贸人都有一颗不安现状的心&#xff1f;总是想挑战一下自己的极限或者是拓宽一下自己未知的领域&#xff1f; 最近遇到一个经常去各个国家参加展会来获取客户的外贸人&#xff0c;他的第一话题不是自己去展会的效果如何&#xff0c;也不是说自己现在做的…

【ChatGPT从瀑布模式到水母模式】如何赋能软件研发全流程?

【文末送书】今天推荐一本强大工具书《ChatGPT 驱动软件开发&#xff1a;AI 在软件研发全流程中的革新与实践》&#xff0c;本文将从其亮点与结构出发&#xff0c;详细阐发其对于运维、项目经理、程序员等的重要性与益处。 文章目录 导语内容作者简介专家推荐读者对象直播预告文…

C++二叉搜索树BinarySearchTree

一、介绍 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或者是具有以下性质的二叉树: 1.若它的左子树不为空&#xff0c;则左子树上所有节点的值都小于根节点的值 2.若它的右子树不为空&#xff0c;则右子树上所有节点的值都大于根节点的值 3.它的左右…

react中的useReducer复杂的状态管理

一、useReducer reducer官网教程 useReducer 是 React 提供的一个用于状态管理的 Hook。它可以替代 useState&#xff0c;更适用于处理复杂的状态逻辑。 useReducer 接受一个reducer函数和一个初始状态&#xff0c;并返回当前状态以及一个 dispatch 函数&#xff0c;用来触发…

【Git企业开发】第五节.远程操作

文章目录 前言一、理解分布式版本控制系统二、远程仓库 2.1 新建远程仓库 2.2 克隆远程仓库 2.3 向远程仓库推送 2.4 拉取远程仓库总结 前言 一、理解分布式版本控制系统 我们目前所说的所有内容(工作区&#xff0c;暂存区&#xff0c;版本库等等)&#x…

geoserver服务shp样式设计

最近在使用geoserver发服务&#xff0c;发影像的时候还没啥感觉&#xff0c;但是到了发shp数据的时候&#xff0c;发完嗯&#xff1f;样式咋是个这&#xff0c;咋看都不满意&#xff0c;于是就搜了搜&#xff0c;看看有什么能设计样式的东西&#xff0c;于是万能网友给了答案&a…

C++之队列queue

1.知识百科 队列是一种特殊的线性表&#xff0c;特殊之处在于它只允许在表的前端&#xff08;front&#xff09;进行删除操作&#xff0c;而在表的后端&#xff08;rear&#xff09;进行插入操作&#xff0c;和栈一样&#xff0c;队列是一种操作受限制的线性表。进行插入操作的…

【Azure】存储服务:Azure 的存储账户

文章目录 一、前提知识&#xff08;建议了解&#xff09;二、介绍 Azure 存储帐户三、使用 Microsoft Azure 门户创建存储帐户 一、前提知识&#xff08;建议了解&#xff09; 在每一个云厂商中&#xff0c;都有自身的云存储&#xff0c;也有根据不同功能进行区分的不同类型的…

资源限流 + 本地分布式多重锁——高并发性能挡板,隔绝无效流量请求

前言 在高并发分布式下&#xff0c;我们往往采用分布式锁去维护一个同步互斥的业务需求&#xff0c;但是大家细想一下&#xff0c;在一些高TPS的业务场景下&#xff0c;让这些请求全部卡在获取分布式锁&#xff0c;这会造成什么问题&#xff1f; 瞬时高并发压垮系统 众所周知…