C++二分算法:最多可以参加的会议数目 II

本文涉及的基础知识点

二分查找算法合集

本题其它解法

C++二分向量算法:最多可以参加的会议数目 II

题目

给你一个 events 数组,其中 events[i] = [startDayi, endDayi, valuei] ,表示第 i 个会议在 startDayi 天开始,第 endDayi 天结束,如果你参加这个会议,你能得到价值 valuei 。同时给你一个整数 k 表示你能参加的最多会议数目。
你同一时间只能参加一个会议。如果你选择参加某个会议,那么你必须 完整 地参加完这个会议。会议结束日期是包含在会议内的,也就是说你不能同时参加一个开始日期与另一个结束日期相同的两个会议。
请你返回能得到的会议价值 最大和 。
示例 1:
输入:events = [[1,2,4],[3,4,3],[2,3,1]], k = 2
输出:7
解释:选择绿色的活动会议 0 和 1,得到总价值和为 4 + 3 = 7 。
示例 2:
输入:events = [[1,2,4],[3,4,3],[2,3,10]], k = 2
输出:10
解释:参加会议 2 ,得到价值和为 10 。
你没法再参加别的会议了,因为跟会议 2 有重叠。你 不 需要参加满 k 个会议。
示例 3:
输入:events = [[1,1,1],[2,2,2],[3,3,3],[4,4,4]], k = 3
输出:9
解释:尽管会议互不重叠,你只能参加 3 个会议,所以选择价值最大的 3 个会议。
**参数范围:
1 <= k <= events.length
1 <= k * events.length <= 106
1 <= startDayi <= endDayi <= 109
1 <= valuei <= 106

分析

时间复杂度

时间复杂度O(knlogn),两层循环。第一层循环循环k-1次,第二层循环循环n次。循环内部查找、插入、删除O(logn)。

变量解释

mPre 记录的上一轮的完成情况,dp是当前轮的完成情况。键对应的是:结束时间,值对应的是:最大会议价值。如果key0 <= key1且value0 >= value1,那么key0会淘汰key1。能选取key1,一定能选取key0,而value0大于等于value1。淘汰后,值保持升序。键小的淘汰键大的。

代码

核心代码

template<class _Kty,class _Ty,bool bValueDdes,bool bOutSmallKey> 
class COrderValueMap 
{
public:void Add (_Kty iValue, _Ty iNum){if (bOutSmallKey){if (bValueDdes){AddOutSmall(iValue, iNum, std::less_equal<_Ty>(), std::greater_equal<_Ty>());}else{}}else {if (bValueDdes){AddNotOutSmall(iValue, iNum, std::greater_equal<_Ty>(), std::less_equal<_Ty>());}else{AddNotOutSmall(iValue, iNum, std::less_equal<_Ty>(), std::greater_equal<_Ty>());}}};template<class _Pr1, class _Pr2>void AddOutSmall(_Kty key, _Ty value, _Pr1 pr1, _Pr2 pr2){auto it = m_map.lower_bound(key);if ((m_map.end() != it) && pr1(it->second, value)){return;//被旧值淘汰}auto ij = it;while (it != m_map.begin()){--it;if (pr2(it->second, value)){it = m_map.erase(it);}}m_map[key] = value;}template<class _Pr1, class _Pr2>void AddNotOutSmall(_Kty key, _Ty value, _Pr1 pr1,_Pr2 pr2 ){auto it = m_map.upper_bound(key);if ((m_map.begin() != it) && pr1(std::prev(it)->second, value)){return;//被淘汰}auto ij = it;for (; (m_map.end() != ij) && pr2(ij->second, value); ++ij);m_map.erase(it, ij);m_map[key] = value;};std::map<_Kty, _Ty> m_map;
};class Solution {
public:int maxValue(vector<vector<int>>& events, int k) {COrderValueMap<int, int, true, false> mPre;for (const auto& v : events){mPre.Add(v[1], v[2]);}while (--k){COrderValueMap<int, int, true, false> dp;for (const auto& v : events){auto it = mPre.m_map.lower_bound(v[0]);int iNewValue = v[2];if (mPre.m_map.begin() != it){iNewValue += std::prev(it)->second;}dp.Add(v[1], iNewValue);}dp.m_map.swap(mPre.m_map);}return mPre.m_map.rbegin()->second;}	
};

测试用例

template <class T>
void Assert(const T& t1, const T& t2)
{assert(t1 == t2);
}template <class T>
void Assert(const vector<T>& v1, const vector<T>& 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<int>> events;int k;int res;{Solution slu;events = { {1,2,4},{3,4,3},{2,3,1} };k = 2;res = slu.maxValue(events, k);Assert(res,7 );}{Solution slu;events = { {1,2,4},{3,4,3},{2,3,10} };k = 2;res = slu.maxValue(events, k);Assert(res, 10);}{Solution slu;events = { {1,1,1},{2,2,2},{3,3,3},{4,4,4} };k = 3;res = slu.maxValue(events, k);Assert(res, 9);}//CConsole::Out(res);}

优化版:第一轮不特殊处理

class Solution {
public:
int maxValue(vector<vector>& events, int k) {
COrderValueMap<int, int, true, false> mPre;
mPre.Add(0, 0);
while (k–)
{
COrderValueMap<int, int, true, false> dp;
for (const auto& v : events)
{
auto it = mPre.m_map.lower_bound(v[0]);
int iNewValue = v[2];
if (mPre.m_map.begin() != it)
{
iNewValue += std::prev(it)->second;
}
dp.Add(v[1], iNewValue);
}
dp.m_map.swap(mPre.m_map);
}
return mPre.m_map.rbegin()->second;
}
};

2023年2月旧代码

class Solution {
public:
int maxValue(vector<vector>& events, int k) {
//dp[i] 已经完成i次会议后的最大值
vector vFinish(k + 1, -1);
vFinish[0] = 0;
std::map<int, vector> mDoing;
std::sort(events.begin(), events.end(), [](const vector& v1, const vector& v2)
{
return v1[0] < v2[0];
});
for (const auto& v : events)
{
while (mDoing.size() && mDoing.begin()->first < v[0])
{
vector& vDoing = mDoing.begin()->second;
for (int iK = 0; iK <= k; iK++)
{
vFinish[iK] = max(vDoing[iK], vFinish[iK]);
}
mDoing.erase(mDoing.begin());
}
vector& vDoing = mDoing[v[1]];
if (0 == vDoing.size())
{
vDoing.resize(k + 1, -1);
}
for (int iK = 0; iK <= k; iK++)
{
vDoing[iK] = max(vDoing[iK], vFinish[iK]);
if (iK > 0)
{
vDoing[iK] = max(vDoing[iK], vFinish[iK-1] + v[2] );
}
}
}
while (mDoing.size() )
{
vector& vDoing = mDoing.begin()->second;
for (int iK = 0; iK <= k; iK++)
{
vFinish[iK] = max(vDoing[iK], vFinish[iK]);
}
mDoing.erase(mDoing.begin());
}
return *std::max_element(vFinish.begin(), vFinish.end());
}
};

2023年9月旧代码

class Solution {
public:
int maxValue(vector<vector>& events, int k) {
m_c = events.size();
vector indexs(m_c);
iota(indexs.begin(), indexs.end(), 0);
sort(indexs.begin(), indexs.end(), [&events](const int& i1, const int& i2)
{
return events[i1][0] < events[i2][0];
});
std::map<int,int> mEndValue;
mEndValue[-1] = 0;
for (int iK = 0; iK < k; iK++)
{
std::map<int, int> dp;
for (const auto& i : indexs)
{
auto it = mEndValue.lower_bound(events[i][0]);
const int iPre = (it == mEndValue.begin()) ? 0 : std::prev(it)->second;
const int iNew = iPre + events[i][2];
auto ij = dp.upper_bound(events[i][1]);
if ((ij != dp.begin()) && (std::prev(ij)->second >= iNew))
{
continue;//前面的数值大,再增意义
}
ij = dp.lower_bound(events[i][1]);
auto tmp = ij;
for (; (tmp != dp.end()) && (tmp->second <= iNew); ++tmp);
dp.erase(ij, tmp);
dp[events[i][1]] = iNew;
}
dp.swap(mEndValue);
}
int iMax = 0;
for (const auto& it : mEndValue)
{
iMax = max(iMax, it.second);
}
return iMax;
}
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

我想对大家说的话
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛

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

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

相关文章

如何在Ubuntu 20.04.6 LTS系统上运行Selenium自动化测试

文章目录 写在前面一、 环境准备1.1 安装python31.1.1 使用APT安装Python31.1.2 使用PPA安装较新版本的Python31.1.3 从源代码编译安装Python31.2 安装pip31.3 安装jdk1.4 安装运行所需浏览器1.4 使用Git拉取自动化测试代码/复制自动化测试代码到Ubuntu 20.04.6 LTS二、安装pip…

Let’s xrOS 一款让你优先体验社区创作者的 visionOS App工具

Let’s xrOS Apple Vision Pro 发布预示着空间计算时代的到来&#xff0c;让科技爱好者和开发者开始思考如何在新的交互、系统和硬件上打造独特的三维应用。 自 WWDC 2023 的发布会后&#xff0c;社交媒体上涌现了许多精美的 visionOS App 的效果图和演示视频&#xff0c;然而…

Rola详解国外住宅IP代理选择的8个方法,稳定的海外IP哪个靠谱?

一、国外住宅IP代理是什么&#xff1f; 代理服务器充当您和互联网之间的网关。它是一个中间服务器&#xff0c;将最终用户与他们浏览的网站分开。如果您使用国外代理IP&#xff0c;互联网流量将通过国外代理服务器流向您请求的地址。然后&#xff0c;请求通过同一个代理服务器…

常见树种(贵州省):014槭树、梧桐、鹅掌楸、檫木、梓木、油桐、泡桐、川楝、麻楝

摘要&#xff1a;本专栏树种介绍图片来源于PPBC中国植物图像库&#xff08;下附网址&#xff09;&#xff0c;本文整理仅做交流学习使用&#xff0c;同时便于查找&#xff0c;如有侵权请联系删除。 图片网址&#xff1a;PPBC中国植物图像库——最大的植物分类图片库 一、色木槭…

java--继承快速入门

1.什么是继承 java中提供了一个关键字extends&#xff0c;用这个关键字&#xff0c;可以让一个类和另一个类建立其父子关系。 2.继承的特点 子类能继承父类的非私有成员(成员变量&#xff0c;成员方法)。 3.继承后对象的创建 子类的对象是由子类、父类共同完成的。 4.继承的…

基于IDEA+HTML+SpringBoot前后端分离电子商城

基于springboot的电子商城 项目介绍&#x1f481;&#x1f3fb; •B2C 商家对客户 •C2B2C 客户对商家对客户 1.1.1 B2C 平台运营方即商品的卖家 小米商城 •商品 •用户 1.1.2 C2B2C 平台运营方不卖商品&#xff08;也可以卖&#xff09; 卖家是平台的用户 买家也是平台用户 •…

『C++成长记』C++入门—— 函数重载引用

&#x1f525;博客主页&#xff1a;小王又困了 &#x1f4da;系列专栏&#xff1a;C &#x1f31f;人之为学&#xff0c;不日近则日退 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、函数重载 &#x1f4d2;1.1函数重载的概念 &#x1f4d2;1.2函数重载的种类 …

基于51单片机音乐盒设计( proteus仿真+程序+原理图+PCB+报告+讲解视频)

音乐盒 主要功能&#xff1a;仿真原理图PCB图程序设计&#xff1a;设计报告实物图资料清单&#xff08;提供资料清单所有文件&#xff09;&#xff1a;资料下载链接&#xff1a; 基于51单片机音乐盒仿真设计( proteus仿真程序原理图PCB报告讲解视频&#xff09; 仿真图proteus …

Python实现交易策略评价指标-收益率

1.收益率的定义 收益率几乎是所有投资者都会关注的一个指标&#xff0c;收益率的高低决定了投资策略的赚钱能力&#xff0c;常见关于收益率的指标如下&#xff1a; 持有期收益率 持有期收益率 期末投资权益 − 期初投资权益 期初投资权益 持有期收益率 \frac {期末投资权益…

GeoTrust SSL数字安全证书介绍

一、GeoTrust OV证书的介绍 GeoTrust OV证书是由GeoTrust公司提供的SSL证书&#xff0c;它是一种支持OpenSSL的数字证书&#xff0c;具有更高的安全性和可信度。GeoTrust是全球领先的网络安全解决方案提供商&#xff0c;为各类用户提供SSL证书和信任管理服务。GeoTrust OV证书…

docker国内镜像加速

创建或修改 /etc/docker/daemon.json 文件&#xff0c;修改为如下形式 {"registry-mirrors": ["https://registry.docker-cn.com","http://hub-mirror.c.163.com","https://docker.mirrors.ustc.edu.cn"] } Docker中国区官方镜像htt…

51单片机应用从零开始(八)·循环语句(for循环、while 语句、do‐while 语句)

51单片机应用从零开始&#xff08;七&#xff09;循环语句&#xff08;if语句&#xff0c;swtich语句&#xff09;-CSDN博客 目录 1. 用for 语句控制蜂鸣器鸣笛次数 2. 用while 语句控制 LED 3. 用 do‐while 语句控制 P0 口 8 位 LED 流水点亮 1. 用for 语句控制蜂鸣器鸣笛…

Kafka 控制器(controller)

Kafka 控制器&#xff08;controller&#xff09; 在kafka集群中 会存在一个或者多个broker&#xff08;一个服务器就是一个broker&#xff09;&#xff0c;其中有一个broker会被选举为控制器 kafka controller &#xff0c;负责管理整个集群中所有副本、分区的状态&#xff0…

多语言快速排序算法

快速排序是一种高效的排序算法&#xff0c;使用分治法策略。它的基本思想是&#xff1a;选择一个元素作为“基准”&#xff08;pivot&#xff09;&#xff0c;重新排序数列&#xff0c;所有比基准值小的元素摆放在基准前面&#xff0c;所有比基准值大的摆在基准的后面。在这个分…

python内置模块binascii,二进制数据和ASCII字符串之间进行转换

一、简介 binascii是Python标准库中的一个模块&#xff0c;提供了在二进制数据和ASCII字符串之间进行转换的功能。它包含了一些用于处理二进制数据的函数&#xff0c;可以进行二进制数据的编码、解码和转换。 二、方法 binascii.unhexlify(hexstr)&#xff1a;将十六进制表示…

事件循环机制及常见面试题

借鉴&#xff1a; 《Javascript 忍者秘籍》第二版&#xff0c;事件循环篇 面试 | JS 事件循环 event loop 经典面试题含答案 - 知乎 (zhihu.com) 概念 主栈队列就是一个宏任务&#xff0c;每一个宏任务执行完就会执行宏任务中的微任务&#xff0c;直到微任务全部都执行完&a…

Python 使用XlsxWriter操作Excel

在数据处理和报告生成的领域中&#xff0c;Excel 文件一直是广泛使用的标准格式。为了让 Python 开发者能够轻松创建和修改 Excel 文件&#xff0c;XlsxWriter 库应运而生。XlsxWriter 是一个功能强大的 Python 模块&#xff0c;专门用于生成 Microsoft Excel 2007及以上版本&a…

Vue3-provide和inject

作用和场景&#xff1a;顶层组件向任意的底层组件传递数据和方法&#xff0c;实现跨层组件通信 跨层传递普通数据&#xff1a; 1.顶层组件通过provide函数提供数据 2.底层组件通过inject函数获取数据 既可以传递普通数据&#xff0c;也可以使用ref传递响应式数据&#xff08…

批量插入SQL 错误 [933] [42000]: ORA-00933: SQL 命令未正确结束

使用DBeaver向【oracle数据库】插入大量数据 INSERT INTO Student(name,sex,age,address,birthday) VALUES(Nike,男,18,北京,2000-01-01) ,(Nike,男,18,北京,2000-01-01) ,(Nike,女,18,北京,2000-01-01) ,(Nike,女,18,北京,2000-01-01) ,(Nike,男,18,北京,2000-01-01) ,(Nike…

使用Arrays.Sort并定制Comparator排序解决合并区间

合并区间-力扣算法题56题 以数组 intervals 表示若干个区间的集合&#xff0c;其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间&#xff0c;并返回 一个不重叠的区间数组&#xff0c;该数组需恰好覆盖输入中的所有区间 。 示例 1&#xff1a; 输入&am…