【区间合并 差分 栈】3169. 无需开会的工作日

news2025/2/26 13:16:59

本文涉及知识点

区间合并
差分数组(大约2024年7月1号发)

LeetCode3169. 无需开会的工作日

给你一个正整数 days,表示员工可工作的总天数(从第 1 天开始)。另给你一个二维数组 meetings,长度为 n,其中 meetings[i] = [start_i, end_i] 表示第 i 次会议的开始和结束天数(包含首尾)。
返回员工可工作且没有安排会议的天数。
注意:会议时间可能会有重叠。

示例 1:
输入:days = 10, meetings = [[5,7],[1,3],[9,10]]
输出:2
解释:
第 4 天和第 8 天没有安排会议。
示例 2:
输入:days = 5, meetings = [[2,4],[1,3]]
输出:1
解释:
第 5 天没有安排会议。
示例 3:
输入:days = 6, meetings = [[1,6]]
输出:0
解释:
所有工作日都安排了会议。
提示:
1 <= days <= 109
1 <= meetings.length <= 105
meetings[i].length == 2
1 <= meetings[i][0] <= meetings[i][1] <= days

差分

days最大109,所以不能有差分数组,只能用差分map,求和的需要有序。
统计开会的时间,比不开会的时间简单。
mDiff[si]++ mDiff[ei+1]-- 表示[si,ei] 一场会议。
∀ \forall mDiff的键 key,其下一个键为nkey。
∀ \forall k ∈ \in [key,nkey) mDiff[k]都为0,省略。
即:
x = ∑ i : 0 k e y m D i f f [ i ] = ∑ i : 0 k m D i f f [ i ] x = \sum_{i:0}^{key}mDiff[i] \quad = \sum_{i:0}^{k}mDiff[i] x=i:0keymDiff[i]=i:0kmDiff[i]
如果x不为0,则[key,nkey)全部要开会。

核心代码

class Solution {
public:
	int countDays(int days, vector<vector<int>>& meetings) {
		map<int, int> mDiff;
		for (const auto& v : meetings) {
			mDiff[v[0]]++;
			mDiff[v[1] + 1]--;
		}
		int iRet = 0;
		int sum = 0;
		for (auto it = mDiff.begin(); std::next(it) != mDiff.end(); ++it) {
			auto itNext = std::next(it);
			sum += it->second;
			if (sum > 0) {
				iRet += itNext->first - it->first;
			}
		}
		return  days - iRet;
	}
};

单元测试

template<class T1,class T2>
void AssertEx(const T1& t1, const T2& t2)
{
	Assert::AreEqual(t1 , t2);
}

template<class T>
void AssertEx(const vector<T>& v1, const vector<T>& v2)
{
	Assert::AreEqual(v1.size(), v2.size());	
	for (int i = 0; i < v1.size(); i++)
	{
		Assert::AreEqual(v1[i], v2[i]);
	}
}

template<class T>
void AssertV2(vector<vector<T>> vv1, vector<vector<T>> vv2)
{
	sort(vv1.begin(), vv1.end());
	sort(vv2.begin(), vv2.end());
	Assert::AreEqual(vv1.size(), vv2.size());
	for (int i = 0; i < vv1.size(); i++)
	{
		AssertEx(vv1[i], vv2[i]);
	}
}

namespace UnitTest
{
	int days;
	vector<vector<int>> meetings;
	TEST_CLASS(UnitTest)
	{
	public:
	
		TEST_METHOD(TestMethod1)
		{
			days = 5, meetings = { {2,4},{1,3} };
			auto res = Solution().countDays(days, meetings);
			AssertEx(1, res);
		}
	
	};
}

封装类

template<class KEY=int,class VALUE=int>
class CMapDiff
{
public:
	void Set(KEY left, KEY rExclue, VALUE value) {
		m_mDiff[left]+= value;
		m_mDiff[rExclue]-= value;
	}
	vector<pair<KEY, VALUE>> Ans()const {
		vector<pair<KEY, VALUE>> res;
		VALUE sum = 0;
		for (const auto& [key,value]: m_mDiff) {			
			sum += value;
			res.emplace_back(make_pair(key, sum));
		}
		return res;
	}
protected:
	map<KEY, VALUE> m_mDiff;
};
class Solution {
public:
	int countDays(int days, vector<vector<int>>& meetings) {
		CMapDiff mDiff;
		for (const auto& v : meetings) {
			mDiff.Set(v[0], v[1] + 1,1);
		}
		auto v = mDiff.Ans();
		int iRet = 0;
		for (int i = 0; i + 1 < v.size(); i++) {
			if( v[i].second > 0 ){ iRet += v[i + 1].first - v[i].first; }			
		}
		return  days - iRet;
	}
};

差分(旧版)

值相同的区间进行了合并,没多大意义。

class Solution {
public:
	int countDays(int days, vector<vector<int>>& meetings) {
		map<int, int> mDiff;
		for (const auto& v : meetings) {
			mDiff[v[0]]++;
			mDiff[v[1]+1]--;
		}

		vector<pair<int, int>> v;
		if (1 != mDiff.begin()->first) {
			v.emplace_back(make_pair(1, 0));
		}
		int sum = 0;
		for (const auto& [day, cnt] : mDiff) {
			sum += cnt;
			v.emplace_back(day, (sum>0));
		}		
		vector<pair<int, int>> v1;
		v1.emplace_back(v[0]);
		for (int i = 1; i < v.size(); i++) {
			if (v[i].second != v1.back().second) {
				v1.emplace_back(v[i]);
			}
		}
		if (v1.back().first <= days) {
			v1.emplace_back(make_pair(days + 1, 0));
		}
		int ret = 0;
		for (int i = 0; i + 1 < v1.size(); i++) {
			if (0 == v1[i].second) {
				ret += v1[i + 1].first - v1[i].first;
			}
		}
		return ret;
	}
};

区间合并

先按开始时间的升序排序。依次入栈,如果当前元素和栈顶元素能合并则合并:开始时间不变,终止时间取两者最大值;否则,直接入栈。

template<class ELE>
void MaxSelf(ELE* seft, const ELE& other)
{
	*seft = max(*seft, other);
}

class Solution {
public:
	int countDays(int days, vector<vector<int>>& meetings) {
		sort(meetings.begin(), meetings.end(), [&](const auto& v1, const auto& v2) {return v1[0] < v2[0]; });
		stack<pair<int, int>> sta;
		for (const auto& v : meetings) {
			if (sta.empty() || (sta.top().second < v[0])) {
				sta.emplace(make_pair(v[0], v[1] + 1));
			}
			else {
				MaxSelf(&sta.top().second, v[1] + 1);
			}
		}
		int iRet = 0;
		while (sta.size()) {
			iRet += sta.top().second - sta.top().first;
			sta.pop();
		}
		return  days - iRet;
	}
};

封装后

class CIntervalMerging
{
public:
	CIntervalMerging( vector<vector<int>> vInterval,bool bIncludeEnd) {
		sort(vInterval.begin(), vInterval.end(), [&](const auto& v1, const auto& v2) {return v1[0] < v2[0]; });
		for (const auto& v : vInterval) {
			if (V.empty() || (V.back().second < v[0])) {
				V.emplace_back(make_pair(v[0], v[1] + bIncludeEnd));
			}
			else {
				V.back().second = max(V.back().second, v[1] + bIncludeEnd);
			}
		}
	}
	vector<pair<int, int>> V;
};
class Solution {
public:
	int countDays(int days, vector<vector<int>>& meetings) {	
		CIntervalMerging im(meetings, true);
		int iRet = std::accumulate(im.V.begin(), im.V.end(), 0, [](auto val, auto pr) {return val + pr.second - pr.first; });
		return  days - iRet;
	}
};

扩展阅读

视频课程

先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771

如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

相关推荐

我想对大家说的话
《喜缺全书算法册》以原理、正确性证明、总结为主。
按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。
有效学习:明确的目标 及时的反馈 拉伸区(难度合适) 专注
闻缺陷则喜(喜缺)是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

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

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

相关文章

简易五子棋

简介 使用Java实现简易五子棋 规则介绍 游戏使用一个标准的1515方格的棋盘&#xff0c;双方分别用黑白两种颜色的棋子进行对战。黑子先行&#xff0c;双方轮流在空棋盘的交叉点上落子&#xff0c;每人一次只能落一子。游戏的目标是让自己的五颗棋子连成一线&#xff0c;这条…

BSCI验厂是什么?

BSCI验厂是指Business Social Compliance Initiative&#xff0c;即倡议商界遵守社会责任组织对BSCI组织成员的全球供应商进行的社会责任审核。以下是对BSCI验厂的详细介绍&#xff1a; 背景介绍&#xff1a; 2003年3月&#xff0c;总部设在比利时布鲁塞尔的对外贸易协会FTA正式…

618网络机顶盒哪个牌子好?内行盘点网络机顶盒排行榜

因工作原因每天都在跟各种类型的网络机顶盒打交道&#xff0c;最近超多朋友问我网络机顶盒哪个牌子好&#xff0c;不知道如何挑选网络机顶盒&#xff0c;我将要分享目前最值得入手的网络机顶盒排行榜&#xff0c;想买网络机顶盒可以看看以下这些品牌&#xff1a; ★泰捷WEBOX 6…

在ubuntu16中下载VMware Tools工具

一、打开植入 二、开始安装 打开驱动放置的默认位置 在这里打开终端&#xff1b;添加到/home/你的用户名/Downloand/中 进入后解压 然后进去解压后的文件 终端输入 sudo ./vmware-install.pl 开始安装前的配置&#xff08;很麻烦跟着输就行&#xff09; 继续 出现如上…

机器学习笔记:focal loss

1 介绍 Focal Loss 是一种在类别不平衡的情况下改善模型性能的损失函数最初在 2017 年的论文《Focal Loss for Dense Object Detection》中提出这种损失函数主要用于解决在有挑战性的对象检测任务中&#xff0c;易分类的负样本占据主导地位的问题&#xff0c;从而导致模型难以…

蓝牙耳机怎么连接电脑?轻松实现无线连接

蓝牙耳机已经成为许多人生活中不可或缺的一部分&#xff0c;不仅可以方便地连接手机&#xff0c;还能轻松连接电脑&#xff0c;让我们在工作和娱乐时享受无线的自由。然而&#xff0c;对于一些用户来说&#xff0c;将蓝牙耳机与电脑连接可能会遇到一些问题。本文将介绍蓝牙耳机…

JAVA面试常见面试问题02

1、jvm 内存结构图 对jvm直观的了解 答&#xff1a; jvm是一个抽象执行环境&#xff0c;它通过加载字节码、实现跨平台运行、管理内存&#xff08;包括自动垃圾回收&#xff09;、优化代码执行等&#xff0c;为Java程序提供运行时支持 2、内存泄漏 和 内存溢出 答&#xf…

错题记录(小测)

单选 错题1 错题2 错题3 代码题 反转链表 链表的回文结构

C++语法08 数据类型之间的强制转换

目录 强制类型转换 强制类型转换格式 整型转换成浮点型 整型转换成浮点型其他写法 训练&#xff1a;糖果奖励 糖果奖励参考代码 浮点型转换成整型 浮点型转换成整型其他写法 训练&#xff1a;分离小数 分离小数参考代码 强制类型转换 强制类型转换&#xff0c;就是把…

碳中和研究院OLED透明屏2x2整机项目方案

一、项目背景 随着全球气候变化和环境问题的日益严重&#xff0c;碳中和成为各国政府和企业的重要议题。为了响应这一趋势&#xff0c;黑龙江碳中和研究院计划引入先进的OLED透明屏技术&#xff0c;以展示其研究成果和碳中和理念。本项目旨在为该研究院提供一套高质量的OLED透明…

域策略笔记

域策略 导航 文章目录 域策略导航一、设置客户端壁纸二、重定向用户配置文件路径三、部署网络打印机四、部署共享文件夹为网络驱动器五、通过域策略推送软件安装六、通过域策略限制软件的使用通过路径进行限制通过进程限制 七、通过域策略将文件添加白名单八、通过域策略添加可…

什么是 Solana 节点?

什么是 Solana 节点&#xff1f; 验证交易和维护安全是任何项目进入权益证明领域时必须执行的强制性活动。如果没有节点运营商&#xff08;验证器和 RPC 节点&#xff09;&#xff0c;Solana 网络就无法实现这些目标。 让我们看看这两种类型的节点有何区别。 共识验证者 角色&…

GenICam标准(三)

系列文章目录 GenICam标准&#xff08;一&#xff09; GenICam标准&#xff08;二&#xff09; GenICam标准&#xff08;三&#xff09; 文章目录 系列文章目录6、缓存7、识别并判断相机描述文件的版本7.1. 格式的版本7.2. 相机描述文件的版本7.3. 识别并缓存相机描述文件 参考…

2024年6月14日 (周五) 叶子游戏新闻

期刊杂志: 聚合读者、意林、知音、故事会、花火以及国内各大知名报纸电子版&#xff0c;无需付费即可观看各种免费资源 WPS免登录一键修改器: 去除烦人的登录且能正常使用 EA招募退伍军人重塑下一代《战地》游戏EA正通过“雇用我们的英雄”计划&#xff08;HOH&#xff09;雇用…

OpenAI函数调用:使用Assistants API函数工具的一个示例

Are you looking to expand GPTs capabilities? Check out this tutorial for a complete example of an AI Assistant that can send emails whenever we ask it to. 您是否希望扩展GPT的功能&#xff1f;查看这个教程&#xff0c;它提供了一个完整的示例&#xff0c;展示了…

多模态革新:Ferret-v2在高分辨率图像理解与细粒度交互的突破

在多模态大模型&#xff08;MLLMs&#xff09;的研究中&#xff0c;如何将视觉理解能力与语言模型相结合&#xff0c;以实现更精细的区域描述和推理&#xff0c;是一个重要的研究方向。先前的工作如Ferret模型&#xff0c;通过整合区域理解能力&#xff0c;提升了模型在对话中的…

开源大模型的新星:ChatGPT-Next-Web 项目解析与推荐

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

蓝卓为中小制造企业注入数字化转型活力

随着劳动力成本上升,原材料价格上涨,企业生产成本逐年增加&#xff0c;市场竞争越来越激烈&#xff0c;传统的中小制造企业面临着巨大的压力。 通过数字化转型应对环境的变化已成为行业共识&#xff0c;在数字化的进程中&#xff0c;中小企业首要考虑生存问题&#xff0c;不能…

Sklearn中逻辑回归建模

分类模型的评估 回归模型的评估方法&#xff0c;主要有均方误差MSE&#xff0c;R方得分等指标&#xff0c;在分类模型中&#xff0c;我们主要应用的是准确率这个评估指标&#xff0c;除此之外&#xff0c;常用的二分类模型的模型评估指标还有召回率&#xff08;Recall&#xff…

串口屏介绍

一、串口屏简介 串口屏&#xff08;Serial LCD/Serial TFT Display&#xff09;是一种集成了串行通讯功能的显示屏&#xff0c;广泛应用于各种嵌入式系统、工业控制、人机界面&#xff08;HMI&#xff09;等领域。该显示屏通过串口&#xff08;如UART、RS232、RS485等&#xf…