区间合并|LeetCode100136:统计好分割方案的数目

news2024/11/26 10:32:46

作者推荐

【动态规划】【广度优先】LeetCode2258:逃离火灾

本文涉及的基础知识点

区间合并

题目

给你一个下标从 0 开始、由 正整数 组成的数组 nums。
将数组分割成一个或多个 连续 子数组,如果不存在包含了相同数字的两个子数组,则认为是一种 好分割方案 。
返回 nums 的 好分割方案 的 数目。
由于答案可能很大,请返回答案对 109 + 7 取余 的结果。
示例 1:
输入:nums = [1,2,3,4]
输出:8
解释:有 8 种 好分割方案 :([1], [2], [3], [4]), ([1], [2], [3,4]), ([1], [2,3], [4]), ([1], [2,3,4]), ([1,2], [3], [4]), ([1,2], [3,4]), ([1,2,3], [4]) 和 ([1,2,3,4]) 。
示例 2:
输入:nums = [1,1,1,1]
输出:1
解释:唯一的 好分割方案 是:([1,1,1,1]) 。
示例 3:
输入:nums = [1,2,1,3]
输出:2
解释:有 2 种 好分割方案 :([1,2,1], [3]) 和 ([1,2,1,3]) 。
参数范围
1 <= nums.length <= 105
1 <= nums[i] <= 109

区间合并

时间复杂度: O(nlogn)

分析

如果存在两个相同的数,则两者必须在同一个子数组。比如:{1,2,1,3},不能像这样分:
一,{1},{2,1,3}
二,{1,2},{1,3}
假定有数组中x有两个或更多,第一个的索引是xi1,最后一个的索引是xi2。在区间[xi1,xi2)处不能被拆分。
如果y也存在2个或更多,且yi1 > xi1,如果yi1 <= xi2,则两个区间合并成[xi1,max(xi2,yi2)]。
处了区间[xi1,xi2] 的[xi1,xi2)共有(xi2-xi1)位不能分块外,其它都可以拆分。
总共有n-1个位置,可以拆分,扣掉各区间不能拆分的位置,假定有m个位置可以拆分,则结果是2m

代码

核心代码

template<int MOD = 1000000007>
class C1097Int
{
public:
	C1097Int(long long llData = 0) :m_iData(llData% MOD)
	{

	}
	C1097Int  operator+(const C1097Int& o)const
	{
		return C1097Int(((long long)m_iData + o.m_iData) % MOD);
	}
	C1097Int& operator+=(const C1097Int& o)
	{
		m_iData = ((long long)m_iData + o.m_iData) % MOD;
		return *this;
	}
	C1097Int& operator-=(const C1097Int& o)
	{
		m_iData = (m_iData + MOD - o.m_iData) % MOD;
		return *this;
	}
	C1097Int  operator-(const C1097Int& o)
	{
		return C1097Int((m_iData + MOD - o.m_iData) % MOD);
	}
	C1097Int  operator*(const C1097Int& o)const
	{
		return((long long)m_iData * o.m_iData) % MOD;
	}
	C1097Int& operator*=(const C1097Int& o)
	{
		m_iData = ((long long)m_iData * o.m_iData) % MOD;
		return *this;
	}
	bool operator<(const C1097Int& o)const
	{
		return m_iData < o.m_iData;
	}
	C1097Int pow(long long n)const
	{
		C1097Int iRet = 1, iCur = *this;
		while (n)
		{
			if (n & 1)
			{
				iRet *= iCur;
			}
			iCur *= iCur;
			n >>= 1;
		}
		return iRet;
	}
	C1097Int PowNegative1()const
	{
		return pow(MOD - 2);
	}
	int ToInt()const
	{
		return m_iData;
	}
private:
	int m_iData = 0;;
};

class Solution {
public:
	int numberOfGoodPartitions(vector<int>& nums) {
		m_c = nums.size();
		std::map<int, int> mLeftRight;
		{
			std::unordered_map<int, std::pair<int, int>> mValueToFirstEnd;
			for (int i = 0; i < m_c; i++)
			{
				if (!mValueToFirstEnd.count(nums[i]))
				{
					mValueToFirstEnd[nums[i]] = std::make_pair(i, i);
				}
				else
				{
					mValueToFirstEnd[nums[i]].second = i;
				}
			}
			for (const auto& [tmp, it] : mValueToFirstEnd)
			{
				mLeftRight[it.first] = it.second;
			}
		}
		vector<std::pair<int, int>> vLeftRight;
		for (auto it = mLeftRight.begin(); it != mLeftRight.end(); ++it)
		{
			int iRight = it->second;
			auto ij = std::next(it);
			while ( (mLeftRight.end() != ij) && (ij->first <= iRight))
			{
				iRight = max(iRight, ij->second);
				ij++;
			}
			mLeftRight.erase(std::next(it), ij);
			vLeftRight.emplace_back(it->first, iRight);
		}
		int iCanSplitPos = m_c - 1;
		for (const auto& [left,right] : vLeftRight)
		{
			iCanSplitPos -= right - left;
		}
		return C1097Int<>(2).pow(iCanSplitPos).ToInt();
	}
	int m_c;
};

测试用例

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]);
	}
}

template<class T>
void Assert(const T& t1, const T& t2)
{
	assert(t1 == t2);
}

int main()
{
	Solution slu;
	vector<int> nums;
	int k;
	{
		Solution slu;
		nums = { 2, 4, 7, 1, 2 };
		auto res = slu.numberOfGoodPartitions(nums);
		Assert(1, res);
	}
	{
		Solution slu;
		nums = { 1,2,1,3 };
		auto res = slu.numberOfGoodPartitions(nums);
		Assert(2,res );
	}
	{
		Solution slu;
		nums = { 1,1,1,1 };
		auto res = slu.numberOfGoodPartitions(nums);
		Assert(1, res);
	}
	

}

优化

最后的循环,可以删除。
class Solution {
public:
int numberOfGoodPartitions(vector& nums) {
m_c = nums.size();
std::map<int, int> mLeftRight;
{
std::unordered_map<int, std::pair<int, int>> mValueToFirstEnd;
for (int i = 0; i < m_c; i++)
{
if (!mValueToFirstEnd.count(nums[i]))
{
mValueToFirstEnd[nums[i]] = std::make_pair(i, i);
}
else
{
mValueToFirstEnd[nums[i]].second = i;
}
}
for (const auto& [tmp, it] : mValueToFirstEnd)
{
mLeftRight[it.first] = it.second;
}
}
int iCanSplitPos = m_c - 1;
for (auto it = mLeftRight.begin(); it != mLeftRight.end(); ++it)
{
int iRight = it->second;
auto ij = std::next(it);
while ( (mLeftRight.end() != ij) && (ij->first <= iRight))
{
iRight = max(iRight, ij->second);
ij++;
}
mLeftRight.erase(std::next(it), ij);
iCanSplitPos -= iRight - it->first;
}
return C1097Int<>(2).pow(iCanSplitPos).ToInt();
}
int m_c;
};

旧代码

template
class C1097Int
{
public:
C1097Int(long long llData = 0) :m_iData(llData% MOD)
{

}
C1097Int  operator+(const C1097Int& o)const
{
	return C1097Int(((long long)m_iData + o.m_iData) % MOD);
}
C1097Int& operator+=(const C1097Int& o)
{
	m_iData = ((long long)m_iData + o.m_iData) % MOD;
	return *this;
}
C1097Int& operator-=(const C1097Int& o)
{
	m_iData = (m_iData + MOD - o.m_iData) % MOD;
	return *this;
}
C1097Int  operator-(const C1097Int& o)
{
	return C1097Int((m_iData + MOD - o.m_iData) % MOD);
}
C1097Int  operator*(const C1097Int& o)const
{
	return((long long)m_iData * o.m_iData) % MOD;
}
C1097Int& operator*=(const C1097Int& o)
{
	m_iData = ((long long)m_iData * o.m_iData) % MOD;
	return *this;
}
bool operator<(const C1097Int& o)const
{
	return m_iData < o.m_iData;
}
C1097Int pow(long long n)const
{
	C1097Int iRet = 1, iCur = *this;
	while (n)
	{
		if (n & 1)
		{
			iRet *= iCur;
		}
		iCur *= iCur;
		n >>= 1;
	}
	return iRet;
}
C1097Int PowNegative1()const
{
	return pow(MOD - 2);
}
int ToInt()const
{
	return m_iData;
}

private:
int m_iData = 0;;
};

class Solution {
public:
int numberOfGoodPartitions(vector& nums) {
m_c = nums.size();
std::map<int, int> mLeftRight;
{
std::unordered_map<int, std::pair<int, int>> mValueToFirstEnd;
for (int i = 0; i < m_c; i++)
{
if (!mValueToFirstEnd.count(nums[i]))
{
mValueToFirstEnd[nums[i]] = std::make_pair(i, i);
}
else
{
mValueToFirstEnd[nums[i]].second = i;
}
}
for (const auto& [tmp, it] : mValueToFirstEnd)
{
mLeftRight[it.first] = it.second;
}
}
vector<std::pair<int, int>> vLeftRight;
vLeftRight.emplace_back(0, 0);
for (auto it = mLeftRight.begin(); it != mLeftRight.end(); ++it)
{
int iRight = it->second;
auto ij = std::next(it);
while ( (mLeftRight.end() != ij) && (ij->first <= iRight))
{
iRight = max(iRight, ij->second);
ij++;
}
mLeftRight.erase(std::next(it), ij);
vLeftRight.emplace_back(it->first, iRight);
}
vLeftRight.emplace_back(m_c-1, m_c-1);
C1097Int<> biRet = 1;
for (int i = 1; i < vLeftRight.size(); i++)
{
C1097Int<> biTmp = 2;
biRet *= biTmp.pow(vLeftRight[i].first - vLeftRight[i - 1].second);
}
return biRet.ToInt();
}
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

我想对大家说的话
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业

。也就是我们常说的专业的人做专业的事。 |
|如果程序是一条龙,那算法就是他的是睛|

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境:

VS2022 C++17

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

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

相关文章

layui分页laypage结合Flask+Jinja2实现流程

Layui2.0普通用法<!DOCTYPE html> <html> <head><meta charset"utf-8"><meta name"viewport" content"widthdevice-width, initial-scale1"><title>Demo</title><!-- 请勿在项目正式环境中引用该 …

使用eXtplorer本地搭建文件管理器并内网穿透远程访问本地数据

文章目录 1. 前言2. eXtplorer网站搭建2.1 eXtplorer下载和安装2.2 eXtplorer网页测试2.3 cpolar的安装和注册 3.本地网页发布3.1.Cpolar云端设置3.2.Cpolar本地设置 4.公网访问测试5.结语 1. 前言 通过互联网传输文件&#xff0c;是互联网最重要的应用之一&#xff0c;无论是…

ThingWorx 9.2 Windows安装

参考官方文档安装配置 1 PostgreSQL 13.X 2 Java, Apache Tomcat, and ThingWorx PTC Help Center 参考这里安装 数据库 C:\ThingworxPostgresqlStorage 设置为任何人可以full control 数据库初始化 pgadmin4 创建用户twadmin并记录口令password Admin Userpostgres Thin…

I.MX6ULL_Linux_驱动篇(46)linux LCD驱动

LCD 是很常用的一个外设&#xff0c;在Linux 下LCD 的使用更加广泛&#xff0c;在搭配 QT 这样的 GUI 库下可以制作出非常精美的 UI 界面。本章我们就来学习一下如何在 Linux 下驱动 LCD 屏幕。 Linux 下 LCD 驱动简析 Framebuffer 设备 先来回顾一下裸机的时候 LCD 驱动是怎…

Leetcode每日一题

https://leetcode.cn/problems/binary-tree-preorder-traversal/ 这道题目需要我们自行进行创建一个数组&#xff0c;题目也给出我们需要自己malloc一个数组来存放&#xff0c;这样能达到我们遍历的效果&#xff0c;我们来看看他的接口函数给的是什么。 可以看到的是这个接口函…

探秘ipa文件签名工具在线签名工具:工作原理和代码表示原理

随着iOS应用程序的兴起&#xff0c;ipa文件的安全性变得越来越重要。为了确保应用程序来源的可信度和完整性&#xff0c;开发者需要对其应用进行签名&#xff0c;并使用正确的证书来验证其身份。在这篇文章中&#xff0c;我们将探索一个名为在线签名工具的ipa文件签名工具&…

指令数据:训练大模型的“隐形助力”

作者&#xff1a;谭婧 &#xff08;一&#xff09;指令数据&#xff0c;了解一下 先聊一件圈内趣事&#xff1a; 2023年初&#xff0c;大约在1月到2月份前后&#xff0c; 百度公司如流工作卡上有一个任务&#xff0c; 让百度员工打开脑洞&#xff0c;写“问答对”。 一问一答都…

智能优化算法应用:基于教与学算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于教与学算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于教与学算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.教与学算法4.实验参数设定5.算法结果6.参考文…

gin投票系统3

对应视频v1版本 1.优化登陆接口 将同步改为异步 原login前端代码&#xff1a; <!doctype html> <html lang"en"> <head><meta charset"utf-8"><title>香香编程-投票项目</title> </head> <body> <m…

分支和回溯

题目&#xff1a;四皇后问题 解空间&#xff1a;四维向量x1,x2,x3,x4 四叉树&#xff1a;定义 每一个节点向下分叉 有四个 就是四叉树 第一个皇后第二个皇后第三个皇后第四个皇后1111222233334444 第一个皇后第二个皇后第三个皇后第四个皇后可行&#xff1f;1324x 2 3 反斜线…

初识Ceph --组件、存储类型、存储原理

目录 ceph组件存储类型块存储文件存储对象存储 存储过程 ceph Ceph&#xff08;分布式存储系统&#xff09;是一个开源的分布式存储系统&#xff0c;设计用于提供高性能、高可靠性和可扩展性的存储服务&#xff0c;可以避免单点故障&#xff0c;支持块存储、对象存储以及文件系…

在IDEA中创建Maven项目时没有src文件、不自动配置文件

错误示例&#xff1a; 没有src文件&#xff0c;并且没有自动下载相关的配置文件 对我这中情况无效的解决办法&#xff1a; ①配置好下列图中圈出来的文件 ②在VM选项中输入&#xff1a;“-DarchetypeInternal” ③点击应用&#xff0c;再点击确定 ④还是不行 解决办法&#x…

为 Compose MultiPlatform 添加 C/C++ 支持(2):在 jvm 平台使用 jni 实现桌面端与 C/C++ 互操作

前言 在上篇文章中我们已经介绍了实现 Compose MultiPlatform 对 C/C 互操作的基本思路。 并且先介绍了在 kotlin native 平台使用 cinterop 实现与 C/C 的互操作。 今天这篇文章将补充在 jvm 平台使用 jni。 在 Compose MultiPlatform 中&#xff0c;使用 jvm 平台的是 An…

React antd如何实现<Upload>组件上传附件再次上传已清除附件缓存问题

最近遇到一个React上传组件的问题&#xff0c;即上传附件成功后&#xff0c;文件展示处仍然还有之前上传附件的缓存信息&#xff0c;需要解决的问题是&#xff0c;要把上一次上传的附件缓存在上传成功或者取消后&#xff0c;可以进行清除 经过一顿试错&#xff0c;终于解决了这…

模块一——双指针:611.有效三角形的个数

文章目录 题目描述算法原理解法一&#xff1a;暴力求解(超时&#xff09;解法二&#xff1a;排序&#xff0b;双指针 代码实现 题目描述 题目链接&#xff1a;611.有效三角形的个数 算法原理 解法一&#xff1a;暴力求解(超时&#xff09; 三层for循环枚举出所有的三元组&…

Linux常见压缩指令小结

为什么需要压缩技术 我们都知道文件是以byte作为单位的&#xff0c;如果我们的文件仅仅在低位占一个1 0000 0001这种情况我们完全可以压缩一下&#xff0c;将高位的0全部抹掉即可。 如上所说是一种压缩技术&#xff0c;还有一种就是将1111(此处省略96个)一共100个1&#xff0…

键盘打字盲打练习系列之成为大师——5

一.欢迎来到我的酒馆 盲打&#xff0c;成为大师&#xff01; 目录 一.欢迎来到我的酒馆二.关于盲打你需要知道三.值得收藏的练习打字网站 二.关于盲打你需要知道 盲打系列教程&#xff0c;终于写到终章了。。。一开始在看网上视频&#xff0c;看到up主熟练的打字技巧&#xff…

mapstruct个人学习记录

mapstruct核心技术学习 简介入门案例maven依赖 IDEA插件单一对象转换测试结果 mapping属性Spring注入的方式测试 集合的映射set类型的映射测试map类型的映射测试 MapMappingkeyDateFormatvalueDateFormat 枚举映射基础入门 简介 在工作中&#xff0c;我们经常要进行各种对象之…

综述 2022-Genome Biology:“AI+癌症multi-omics”融合方法benchmark

Leng, Dongjin, et al. "A benchmark study of deep learning-based multi-omics data fusion methods for cancer." Genome biology 23.1 (2022): 1-32. 被引次数&#xff1a;34作者单位 红色高亮表示写论文中可以借鉴的地方 一、方法和数据集 1. 3个数据集&…

【数学建模】《实战数学建模:例题与讲解》第八讲-回归分析(含Matlab代码)

【数学建模】《实战数学建模&#xff1a;例题与讲解》第八讲-回归分析&#xff08;含Matlab代码&#xff09; 回归分析基本概念经典多元线性回归&#xff08;MLR&#xff09;主成分回归&#xff08;PCR&#xff09;偏最小二乘回归&#xff08;PLS&#xff09;建模过程应用和优势…