map|动态规划|单调栈|LeetCode975:奇偶跳

news2024/9/22 7:41:20

作者推荐

【贪心算法】【中位贪心】.执行操作使频率分数最大

涉及知识点

单调栈 动态规划 map

题目

给定一个整数数组 A,你可以从某一起始索引出发,跳跃一定次数。在你跳跃的过程中,第 1、3、5… 次跳跃称为奇数跳跃,而第 2、4、6… 次跳跃称为偶数跳跃。
你可以按以下方式从索引 i 向后跳转到索引 j(其中 i < j):
在进行奇数跳跃时(如,第 1,3,5… 次跳跃),你将会跳到索引 j,使得 A[i] <= A[j],A[j] 是可能的最小值。如果存在多个这样的索引 j,你只能跳到满足要求的最小索引 j 上。
在进行偶数跳跃时(如,第 2,4,6… 次跳跃),你将会跳到索引 j,使得 A[i] >= A[j],A[j] 是可能的最大值。如果存在多个这样的索引 j,你只能跳到满足要求的最小索引 j 上。
(对于某些索引 i,可能无法进行合乎要求的跳跃。)
如果从某一索引开始跳跃一定次数(可能是 0 次或多次),就可以到达数组的末尾(索引 A.length - 1),那么该索引就会被认为是好的起始索引。
返回好的起始索引的数量。
示例 1:
输入:[10,13,12,14,15]
输出:2
解释:
从起始索引 i = 0 出发,我们可以跳到 i = 2,(因为 A[2] 是 A[1],A[2],A[3],A[4] 中大于或等于 A[0] 的最小值),然后我们就无法继续跳下去了。
从起始索引 i = 1 和 i = 2 出发,我们可以跳到 i = 3,然后我们就无法继续跳下去了。
从起始索引 i = 3 出发,我们可以跳到 i = 4,到达数组末尾。
从起始索引 i = 4 出发,我们已经到达数组末尾。
总之,我们可以从 2 个不同的起始索引(i = 3, i = 4)出发,通过一定数量的跳跃到达数组末尾。
示例 2:
输入:[2,3,1,1,4]
输出:3
解释:
从起始索引 i=0 出发,我们依次可以跳到 i = 1,i = 2,i = 3:
在我们的第一次跳跃(奇数)中,我们先跳到 i = 1,因为 A[1] 是(A[1],A[2],A[3],A[4])中大于或等于 A[0] 的最小值。
在我们的第二次跳跃(偶数)中,我们从 i = 1 跳到 i = 2,因为 A[2] 是(A[2],A[3],A[4])中小于或等于 A[1] 的最大值。A[3] 也是最大的值,但 2 是一个较小的索引,所以我们只能跳到 i = 2,而不能跳到 i = 3。
在我们的第三次跳跃(奇数)中,我们从 i = 2 跳到 i = 3,因为 A[3] 是(A[3],A[4])中大于或等于 A[2] 的最小值。
我们不能从 i = 3 跳到 i = 4,所以起始索引 i = 0 不是好的起始索引。
类似地,我们可以推断:
从起始索引 i = 1 出发, 我们跳到 i = 4,这样我们就到达数组末尾。
从起始索引 i = 2 出发, 我们跳到 i = 3,然后我们就不能再跳了。
从起始索引 i = 3 出发, 我们跳到 i = 4,这样我们就到达数组末尾。
从起始索引 i = 4 出发,我们已经到达数组末尾。
总之,我们可以从 3 个不同的起始索引(i = 1, i = 3, i = 4)出发,通过一定数量的跳跃到达数组末尾。
示例 3:
输入:[5,1,3,4,2]
输出:3
解释:
我们可以从起始索引 1,2,4 出发到达数组末尾。
提示:
1 <= A.length <= 20000
0 <= A[i] < 100000

代码

单调栈

此方法比map巧妙,性能差不多,值得学习。时间复杂度:O(nlogn)。

变量函数解析

indexs计算奇数跳时,arr[index[i]] 升序,且相等的元素,相对顺序不变。计算偶数跳时,arr[index[i]] 降序,且相等的元素,相对顺序不变。
Next计算奇(偶)数跳的下一个位置,如果无法跳,则值为m_c
vStatus记录偶数(奇数)跳能否跳到队尾。vStatus[0][m_c]和vStatus[0][m_c]为false,避免处理边界条件

Next奇数跳为例

令j=index[jj],按jj从小到的顺序,将j入栈,由于arr[index[jj]]是升序,所以:规则一:arr[栈中元素] <=arr[j]。
(sta.top() < j 成立,说明:
规则二:j在sta.top()右边。
规则三:令index[jj2] 为sta.top(),arr[index(jj2,j)]中的数(即大于等于arr[sta.top()] 同时小于等于arr[j]的数)全部在sta.top()的左边,否则出栈了。
结合规则一二三,stat.top()的下一步就是j。

核心代码

class Solution {
public:
	int oddEvenJumps(vector<int>& arr) {
		m_c = arr.size();
		vector<int> indexs(m_c);
		iota(indexs.begin(), indexs.end(), 0);
		sort(indexs.begin(), indexs.end(), [&](const int i1, const int i2) {return (arr[i1] < arr[i2]) || ((arr[i1] == arr[i2]) && (i1 < i2)); });
		const auto& v1 = Next(indexs);
		sort(indexs.begin(), indexs.end(), [&](const int i1, const int i2) {return (arr[i1] > arr[i2]) || ((arr[i1] == arr[i2]) && (i1 < i2)); });
		const auto& v2 = Next(indexs);

		vector<vector<bool>> vStatus(2, vector<bool>(m_c+1));
		int iRet = 1;
		vStatus[0][m_c-1] = true;
		vStatus[1][m_c - 1] = true;
		for (int i = m_c - 1 - 1; i >= 0; i--)
		{
			vStatus[0][i] = vStatus[1][v2[i]];//偶数跳
			vStatus[1][i] = vStatus[0][v1[i]];//奇数跳
			iRet +=  (int)vStatus[1][i];
		}
		return iRet;
	}
	vector<int> Next(const vector<int>& indexs)
	{
		vector<int> vNext(indexs.size(), indexs.size());
		stack<int> sta;
		for (int j : indexs)
		{
			while (sta.size() && (sta.top() < j))
			{
				vNext[sta.top()] = j;
				sta.pop();
			}
			sta.emplace(j);
		}
		return vNext;
	}
	int m_c;
};

测试用例

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<int> arr;
	{
		Solution slu;
		arr = { 10,13,12,14,15 };
		auto res = slu.oddEvenJumps(arr);
		Assert(2, res);
	}
	{
		Solution slu;
		arr = { 2,3,1,1,4 };
		auto res = slu.oddEvenJumps(arr);
		Assert(3, res);
	}
	{
		Solution slu;
		arr = { 5,1,3,4,2 };
		auto res = slu.oddEvenJumps(arr);
		Assert(3, res);
	}
	
	
	//CConsole::Out(res);
}

2023年3月版:map

利用map性能和单调栈差不多,好理解。从后向前遍历各元素,map的键对应arr[i],map的值对应i。如果arr[i],i小的(后加入的)覆盖前面的。
时间复杂度:O(nlogn)。

map

map可以分成有序(单调)map和无序(哈希)map。还可分成单键map和多键map(允许重复的键)。

 class Solution {
 public:
	 int oddEvenJumps(vector<int>& arr) {
		 vector<vector<bool>> result;
		 result.assign(arr.size(), vector<bool>(2));
		 result[arr.size() - 1][0] = true;
		 result[arr.size() - 1][1] = true;
		 std::map<int, int> mValueIndex;
		 mValueIndex[arr.back()] = arr.size()-1;
		 for (int i = arr.size() - 2; i >= 0; i--)
		 {
			 {//奇数跳跃
				 auto it = mValueIndex.lower_bound(arr[i]);
				 if (mValueIndex.end() != it)
				 {
					 result[i][0] = result[it->second][1];
				 }
			 }
			 {//偶数跳跃
			 auto it2 = mValueIndex.upper_bound(arr[i]);
			 if (mValueIndex.begin() != it2)
			 {
				 --it2;
				 result[i][1] = result[it2->second][0];
			 }
			 mValueIndex[arr[i]] = i;
		 }
		 }
		 int iNum = 0;
		 for (int i = 0; i < arr.size(); i++)
		 {
			 if (result[i][0])
			 {
				 iNum++;
			 }
		 }
		 return iNum;
	 }
 };

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步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
如无特殊说明,本算法C++ 实现。

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

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

相关文章

关于Python里xlwings库对Excel表格的操作(十五)

这篇小笔记主要记录如何【获取单元格数据的对齐方式或更改单元格数据的对齐方式】。 前面的小笔记已整理成目录&#xff0c;可点链接去目录寻找所需更方便。 【目录部分内容如下】【点击此处可进入目录】 &#xff08;1&#xff09;如何安装导入xlwings库&#xff1b; &#xf…

【模式识别】解锁降维奥秘:深度剖析PCA人脸识别技术

​&#x1f308;个人主页&#xff1a;Sarapines Programmer&#x1f525; 系列专栏&#xff1a;《模式之谜 | 数据奇迹解码》⏰诗赋清音&#xff1a;云生高巅梦远游&#xff0c; 星光点缀碧海愁。 山川深邃情难晤&#xff0c; 剑气凌云志自修。 目录 &#x1f30c;1 初识模式识…

二维码智慧门牌管理系统:实现数据通信安全

文章目录 前言一、传输隧道加密技术二、传输数据加密技术三、数据接入鉴权技术 前言 随着信息技术的蓬勃发展&#xff0c;智慧门牌管理系统已成为现代商业和家庭重要的一部分。然而&#xff0c;系统普及的同时也带来了数据通信安全的突出问题。为了解决这一挑战&#xff0c;二…

【设计模式-2.5】创建型——建造者模式

说明&#xff1a;本文介绍设计模式中&#xff0c;创建型设计模式中的最后一个&#xff0c;建造者模式&#xff1b; 入学报道 创建型模式&#xff0c;关注于对象的创建&#xff0c;建造者模式也不例外。假设现在有一个场景&#xff0c;高校开学&#xff0c;学生、教师、职工都…

【新版HI3559AV100开发注意事项(二)】

#新版HI3559AV100开发注意事项&#xff08;二&#xff09; 十一、请问海思HI3559AV100 SPC030资料里面的HI3559ADMEB_VER_C_PCB.pcb是用什么软件打开啊&#xff1f; 答&#xff1a;PADS VX 2.2 Altium designer 十二、hi3559级联问题请教 在SDK的文档中只看到了两块Hi3559板…

ARM GIC(一) cortex-A 处理器中断简介

对于ARM的处理器,中断给处理器提供了触觉,使处理器能够感知到外界的变化,从而实时的处理。本系列博文,是以ARM cortex-A系列处理器,来介绍ARM的soc中,中断的处理。 ARM cortex-A系列处理器,提供了4个管脚给soc,实现外界中断的传递。分别是: nIRQ: 物理普通中断 nF…

利用Spark构建房价分析与推荐系统:基于58同城数据的大数据实践

利用Spark构建房价分析与推荐系统&#xff1a;基于58同城数据的大数据实践 基于Spark的房价数据分析预测推荐系统引言技术栈功能概述项目实现1. 数据爬取与处理2. 大数据分析与可视化3. 房价预测模型4. 协同过滤推荐系统5. Web应用开发6. 数据管理与用户管理 总结与展望 基于Sp…

优维科技荣获第二届中国赛宝信息技术应用创新优秀解决方案三等奖

近日&#xff0c;“第二届中国赛宝信息技术应用创新优秀解决方案”评选活动圆满结束。优维科技所提交的《Hyperlnsight超融合持续观测解决方案》、《EasyOps一体化运维平台》从全国近300份申报方案中脱颖而出&#xff0c;荣获2023中国赛宝信息技术应用创新优秀解决方案奖。 本…

Python - 深夜数据结构与算法之 Tree

目录 一.引言 二.树与二叉树简介 1.Tree 树 2.Binary Tree 二叉树 3.Binary Search Tree 二叉搜索树 三.经典算法实战 1.In-Order-Traversal [94] 2.Pre-Order-Traversal [144] 3.Fib [509] 4.N-Tree-Pre-Order-Traversal [589] 5.N-Tree-Post-Order-Traversal [590…

改变传媒格局的新趋势

在如今信息高速发展的时代&#xff0c;人们早已进入了一个以手机为中心的智能化时代。随着科技的迅猛发展&#xff0c;手机无人直播成为了一种新兴的传媒形态&#xff0c;正逐渐改变着传媒格局。本文将从手机无人直播的定义、发展背景和影响等方面进行探讨。 首先&#xff0c;…

浏览器缓存机制(详)

目录 1&#xff0c;缓存的分类1.1&#xff0c;按缓存位置1&#xff0c;Service Worker2&#xff0c;Memory Cache3&#xff0c;Disk Cache4&#xff0c;Push Cache 1.2&#xff0c;按缓存类型强缓存ExpiresCache-control 协商缓存Last-Modified & If-Modified-SinceEtag &a…

【优化】XXLJOB修改为使用虚拟线程

【优化】XXLJOB修改为使用虚拟线程 新建这几个目录 类&#xff0c; 去找项目对应的xxljob的源码 主要是将 new Thread 改为 虚拟线程 Thread.ofVirtual().name("VT").unstarted 以下代码是 xxljob 2.3.0版本 举一反三 去修改对应版本的代码 <!-- 定…

UG螺旋线命令的使用

螺旋线按照螺距类型可以分为两种类型&#xff1a; 1、等螺距螺旋线 2、变螺距螺旋线 等螺距螺旋线 变螺距螺旋线 沿矢量螺旋线 沿矢量螺旋线-线性大小和螺距 沿矢量螺旋线-沿脊线的线性 沿矢量螺旋线-沿脊线的线性 当我们想模拟弹簧被拉伸或压缩状态时&#xff0c;可以使用…

Python-基于fastapi实现SSE流式返回(类似GPT)

最近在做大模型对话相关功能&#xff0c;需要将对话内容流式返回给前端页面&#xff08;类似GPT的效果&#xff09;。下面直接说下如何实现&#xff1a; 1.首先导入fastapi和sse流式返回所需要的包 from fastapi import APIRouter, Response, status from sse_starlette.sse …

智能化运输与航空航天:发展历程、问题与未来趋势

导言 智能化运输与航空航天是当前科技领域的研究热点之一&#xff0c;本文将深入研究这一领域的发展历程、遇到的问题、解决过程&#xff0c;以及未来的可用范围。同时&#xff0c;我们将探讨各国在这一领域的应用情况和未来的研究趋势&#xff0c;分析在哪些方面能够取胜&…

Java操作Word修订功能:启用、接受、拒绝、获取修订

Word的修订功能是一种在文档中进行编辑和审阅的功能。它允许多个用户对同一文档进行修改并跟踪这些修改&#xff0c;以便进行审查和接受或拒绝修改。修订功能通常用于团队合作、专业编辑和文件审查等场景。 本文将从以下几个方面介绍如何使用免费工具Free Spire.Doc for Java在…

数据挖掘体系介绍

数据挖掘是什么&#xff1f; 简而言之&#xff0c;对数据进行挖掘&#xff0c;从中提取出有效的信息。一般我们会把这种信息通过概念、规则、规律、模式等有组织的方式展示出来&#xff0c;形成所谓的知识。特别是在这个大数据时代&#xff0c;当数据多到一定程度&#xff0c;…

shell 数组的详细用法

简介 数组是一种数据结构&#xff0c;用于存储和处理一组相关的数据元素。数组可以包含多个值&#xff0c;每个值都有一个索引&#xff0c;用于标识和访问它们。 目录 1. 数组的基本用法 1.1. 定义数组的方式 1.1.1. 直接赋值 1.1.2. declare声明数组 1.1.3. 索引赋值 1.…

山景DU561—32位高性能音频处理器(DSP)芯片

音频处理可以更好地捕捉和处理声音和音乐&#xff1b;而DSP音频处理芯片是一种利用数字信号处理技术进行音频处理的专用芯片&#xff1b;可用于多种应用&#xff0c;从音乐拾音到复杂的音频信号处理&#xff0c;和声音增强。 由工采网代理的山景DU561是一款集成多种音效算法高…

YOLOv5改进 | 卷积篇 | 通过RFAConv重塑空间注意力(深度学习的前沿突破)

一、本文介绍 本文给大家带来的改进机制是RFAConv&#xff0c;全称为Receptive-Field Attention Convolution&#xff0c;是一种全新的空间注意力机制。与传统的空间注意力方法相比&#xff0c;RFAConv能够更有效地处理图像中的细节和复杂模式(适用于所有的检测对象都有一定的…