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

简介: 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);

}

正确解法

变量含义

mXToYS key为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


相关文章
|
1天前
|
人工智能 自然语言处理 供应链
从第十批算法备案通过名单中分析算法的属地占比、行业及应用情况
2025年3月12日,国家网信办公布第十批深度合成算法通过名单,共395款。主要分布在广东、北京、上海、浙江等地,占比超80%,涵盖智能对话、图像生成、文本生成等多行业。典型应用包括医疗、教育、金融等领域,如觅健医疗内容生成算法、匠邦AI智能生成合成算法等。服务角色以面向用户为主,技术趋势为多模态融合与垂直领域专业化。
|
2天前
|
人工智能 自然语言处理 算法
从第九批深度合成备案通过公示名单分析算法备案属地、行业及应用领域占比
2024年12月20日,中央网信办公布第九批深度合成算法名单。分析显示,教育、智能对话、医疗健康和图像生成为核心应用领域。文本生成占比最高(57.56%),涵盖智能客服、法律咨询等;图像/视频生成次之(27.32%),应用于广告设计、影视制作等。北京、广东、浙江等地技术集中度高,多模态融合成未来重点。垂直行业如医疗、教育、金融加速引入AI,提升效率与用户体验。
|
6天前
|
存储 算法 数据处理
公司局域网管理中的哈希表查找优化 C++ 算法探究
在数字化办公环境中,公司局域网管理至关重要。哈希表作为一种高效的数据结构,通过哈希函数将关键值(如IP地址、账号)映射到数组索引,实现快速的插入、删除与查找操作。例如,在员工登录验证和设备信息管理中,哈希表能显著提升效率,避免传统线性查找的低效问题。本文以C++为例,展示了哈希表在局域网管理中的具体应用,包括设备MAC地址与IP分配的存储与查询,并探讨了优化哈希函数和扩容策略,确保网络管理高效准确。
|
6天前
|
存储 负载均衡 算法
基于 C++ 语言的迪杰斯特拉算法在局域网计算机管理中的应用剖析
在局域网计算机管理中,迪杰斯特拉算法用于优化网络路径、分配资源和定位故障节点,确保高效稳定的网络环境。该算法通过计算最短路径,提升数据传输速率与稳定性,实现负载均衡并快速排除故障。C++代码示例展示了其在网络模拟中的应用,为企业信息化建设提供有力支持。
37 15
|
8天前
|
存储 人工智能 算法
通过Milvus内置Sparse-BM25算法进行全文检索并将混合检索应用于RAG系统
阿里云向量检索服务Milvus 2.5版本在全文检索、关键词匹配以及混合检索(Hybrid Search)方面实现了显著的增强,在多模态检索、RAG等多场景中检索结果能够兼顾召回率与精确性。本文将详细介绍如何利用 Milvus 2.5 版本实现这些功能,并阐述其在RAG 应用的 Retrieve 阶段的最佳实践。
通过Milvus内置Sparse-BM25算法进行全文检索并将混合检索应用于RAG系统
|
13天前
|
运维 监控 算法
监控局域网其他电脑:Go 语言迪杰斯特拉算法的高效应用
在信息化时代,监控局域网成为网络管理与安全防护的关键需求。本文探讨了迪杰斯特拉(Dijkstra)算法在监控局域网中的应用,通过计算最短路径优化数据传输和故障检测。文中提供了使用Go语言实现的代码例程,展示了如何高效地进行网络监控,确保局域网的稳定运行和数据安全。迪杰斯特拉算法能减少传输延迟和带宽消耗,及时发现并处理网络故障,适用于复杂网络环境下的管理和维护。
|
14天前
|
存储 缓存 监控
企业监控软件中 Go 语言哈希表算法的应用研究与分析
在数字化时代,企业监控软件对企业的稳定运营至关重要。哈希表(散列表)作为高效的数据结构,广泛应用于企业监控中,如设备状态管理、数据分类和缓存机制。Go 语言中的 map 实现了哈希表,能快速处理海量监控数据,确保实时准确反映设备状态,提升系统性能,助力企业实现智能化管理。
28 3
|
15天前
|
算法 安全 Java
探讨组合加密算法在IM中的应用
本文深入分析了即时通信(IM)系统中所面临的各种安全问题,综合利用对称加密算法(DES算法)、公开密钥算法(RSA算法)和Hash算法(MD5)的优点,探讨组合加密算法在即时通信中的应用。
17 0
|
15天前
|
存储 监控 算法
公司监控上网软件架构:基于 C++ 链表算法的数据关联机制探讨
在数字化办公时代,公司监控上网软件成为企业管理网络资源和保障信息安全的关键工具。本文深入剖析C++中的链表数据结构及其在该软件中的应用。链表通过节点存储网络访问记录,具备高效插入、删除操作及节省内存的优势,助力企业实时追踪员工上网行为,提升运营效率并降低安全风险。示例代码展示了如何用C++实现链表记录上网行为,并模拟发送至服务器。链表为公司监控上网软件提供了灵活高效的数据管理方式,但实际开发还需考虑安全性、隐私保护等多方面因素。
21 0
公司监控上网软件架构:基于 C++ 链表算法的数据关联机制探讨
|
17天前
|
算法 Java 索引
算法系列之搜素算法-二分查找
二分查找是一种在`有序`数组中查找特定元素的算法。它的基本思想是通过将数组分成两半,逐步缩小查找范围,直到找到目标元素或确定目标元素不存在。
30 9
算法系列之搜素算法-二分查找

热门文章

最新文章