[二分查找]LeetCode1964:找出到每个位置为止最长的有效障碍赛跑路线

本文涉及的基础知识点

二分查找算法合集

作者推荐

动态规划LeetCode2552:优化了6版的1324模式

题目

你打算构建一些障碍赛跑路线。给你一个 下标从 0 开始 的整数数组 obstacles ,数组长度为 n ,其中 obstacles[i] 表示第 i 个障碍的高度。
对于每个介于 0 和 n - 1 之间(包含 0 和 n - 1)的下标 i ,在满足下述条件的前提下,请你找出 obstacles 能构成的最长障碍路线的长度:
你可以选择下标介于 0 到 i 之间(包含 0 和 i)的任意个障碍。
在这条路线中,必须包含第 i 个障碍。
你必须按障碍在 obstacles 中的 出现顺序 布置这些障碍。
除第一个障碍外,路线中每个障碍的高度都必须和前一个障碍 相同 或者 更高 。
返回长度为 n 的答案数组 ans ,其中 ans[i] 是上面所述的下标 i 对应的最长障碍赛跑路线的长度。
示例 1:
输入:obstacles = [1,2,3,2]
输出:[1,2,3,3]
解释:每个位置的最长有效障碍路线是:

  • i = 0: [1], [1] 长度为 1
  • i = 1: [1,2], [1,2] 长度为 2
  • i = 2: [1,2,3], [1,2,3] 长度为 3
  • i = 3: [1,2,3,2], [1,2,2] 长度为 3
    示例 2:
    输入:obstacles = [2,2,1]
    输出:[1,2,1]
    解释:每个位置的最长有效障碍路线是:
  • i = 0: [2], [2] 长度为 1
  • i = 1: [2,2], [2,2] 长度为 2
  • i = 2: [2,2,1], [1] 长度为 1
    示例 3:
    输入:obstacles = [3,1,5,6,4,2]
    输出:[1,1,2,3,2,2]
    解释:每个位置的最长有效障碍路线是:
  • i = 0: [3], [3] 长度为 1
  • i = 1: [3,1], [1] 长度为 1
  • i = 2: [3,1,5], [3,5] 长度为 2, [1,5] 也是有效的障碍赛跑路线
  • i = 3: [3,1,5,6], [3,5,6] 长度为 3, [1,5,6] 也是有效的障碍赛跑路线
  • i = 4: [3,1,5,6,4], [3,4] 长度为 2, [1,4] 也是有效的障碍赛跑路线
  • i = 5: [3,1,5,6,4,2], [1,2] 长度为 2
    参数范围
    n == obstacles.length
    1 <= n <= 105
    1 <= obstacles[i] <= 107

分析:二分有序映射

时间复杂度

O(nlogn),枚举终点O(n),每个终点二分查找O(logn)。

变量解析

mHeightNum,键是路障搞定,值是以当前路障为终点的最长路障路线。

代码

template<class _Kty,class _Ty,bool bValueDdes,bool bOutSmallKey>
class COrderValueMap
{
public:
void Add (_Kty key, _Ty value)
{
if (bOutSmallKey)
{
if (bValueDdes)
{
AddOutSmall(key, value, std::less_equal<_Ty>(), std::greater_equal<_Ty>());
}
else
{
assert(false);
}
}
else
{
if (bValueDdes)
{
AddNotOutSmall(key, value, std::greater_equal<_Ty>(), std::less_equal<_Ty>());
}
else
{
AddNotOutSmall(key, value, std::less_equal<_Ty>(), std::greater_equal<_Ty>());
}
}
};
std::map<_Kty, _Ty> m_map;
protected:
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;
};

};

class Solution {
public:
vector longestObstacleCourseAtEachPosition(vector& obstacles) {
COrderValueMap<int, int, true, false> mHeightNum;
vector vRet;
for (const auto& n : obstacles)
{
auto it = mHeightNum.m_map.upper_bound(n);
const int iCurNum = (mHeightNum.m_map.begin() == it) ? 1 : (1 + std::prev(it)->second);
vRet.emplace_back(iCurNum);
mHeightNum.Add(n, iCurNum);
}
return vRet;
}
};

二分有序向量

vLenToMin[i]表示长度为i的路障,终点路障高度为:vLenToMin[i]。如果有相同的路障长度,终点路障高度取最小值。

代码

 class Solution {public:vector<int> longestObstacleCourseAtEachPosition(vector<int>& obstacles) {vector<int> vLenToMin = { 0 };vector<int> vRet;for (const auto& n : obstacles){int index = std::upper_bound(vLenToMin.begin(), vLenToMin.end(),n) - vLenToMin.begin();if (index >= vLenToMin.size()){vLenToMin.emplace_back(n);}else{vLenToMin[index] = min(vLenToMin[index], n);}vRet.emplace_back(index);}return vRet;}};

2023年3月版旧代码

class Solution {
public:
vector longestObstacleCourseAtEachPosition(vector& obstacles) {
std::map<int, int> mHeightNum;
vector vRet;
for (const auto& obs : obstacles)
{
auto it = mHeightNum.upper_bound(obs);
int iNum = 1;
if (mHeightNum.begin() != it)
{
auto tmp = it;
iNum = (–tmp)->second+1;
}
if (mHeightNum.end() != it)
{
if (iNum >= it->second)
{
mHeightNum.erase(it);
}
}
mHeightNum[obs] = iNum;
vRet.push_back(iNum);
}
return vRet;
}
};

2023年7月旧代码

class Solution {
public:
vector longestObstacleCourseAtEachPosition(vector& obstacles) {
std::vector vHeight(obstacles.begin(), obstacles.end());
sort(vHeight.begin(), vHeight.end());
vHeight.erase(std::unique(vHeight.begin(), vHeight.end()), vHeight.end());
std::unordered_map<int, int> mValueToIndex;
for (int i = 0; i < vHeight.size(); i++)
{
mValueToIndex[vHeight[i]] = i;
}
CMaxLineTree tree(mValueToIndex.size());
vector vRet;
for (const auto& n : obstacles)
{
const int index = mValueToIndex[n];
const auto iRet = tree.Query(0, index) + 1;
vRet.emplace_back(iRet);
tree.Modify(index, iRet);
}
return vRet;
}
};

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步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.mzph.cn/news/189509.shtml

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

相关文章

flutter开发实战-实现获取视频的缩略图封面video_thumbnail

flutter开发实战-实现获取视频的缩略图封面video_thumbnail 在很多时候&#xff0c;我们查看视频的时候&#xff0c;视频没有播放时候&#xff0c;会显示一张封面&#xff0c;可能封面没有配置图片&#xff0c;这时候就需要通过获取视频的缩略图来显示封面了。这里使用了video…

第0篇红队笔记-APT-HTB

nmap 80 port-web尝试 searchploit-无结果 资源隐写查看-无结果 135 port rpcclient rpcinfo.py rpcdump.py rpcmap.py rpcmap.py爆破UUID 查看该UUID的表代表的服务能搜到UUID的漏洞 IOXIDResolver提取IPv6地址 IPV6-nmap smb smb探测目录 文件下载 测试其他目录 zip文件…

Quirks(怪癖)模式是什么?它和 Standards(标准)模式有什么区别?

前言: "Quirks模式"和"Standards模式"是与HTML文档渲染模式相关的两种模式。它们影响着浏览器如何解释和渲染HTML和CSS。理解它们之间的区别对于前端开发者和网页设计师来说是至关重要的。本文将深入讨论Quirks模式和Standards模式的区别&#xff0c;以及它…

vscode如何在没有网络的情况下安装插件

vscode如何在没有网络的情况下安装插件 start 遇到没有网络的电脑&#xff0c;无法直接从插件市场安装vscode的插件。写一下 vscode 插件离线安装的方法. 解决方案 目标电脑没有可以安装插件的网络&#xff0c;那我们只能在有网络的环境下载好我们的插件。然后拷贝软件到无…

一文解决msxml3.dll文件缺失问题,快速修复msxml3.dll

在了解问题之前&#xff0c;我们必须首先清楚msxml3.dll到底是什么。DLL&#xff08;Dynamic Link Libraries&#xff09;文件是Windows操作系统使用的一个重要组成部分&#xff0c;用于存储执行特定操作或任务的代码和数据。msxml3.dll为Windows系统提供处理XML文档的功能。如…

键盘打字盲打练习系列之指法练习——2

一.欢迎来到我的酒馆 盲打&#xff0c;指法练习&#xff01; 目录 一.欢迎来到我的酒馆二.开始练习 二.开始练习 前面一个章节简单地介绍了基准键位、字母键位和数字符号键位指法&#xff0c;在这个章节详细介绍指法。有了前面的章节的基础练习&#xff0c;相信大家对盲打也有了…

Ubuntu 2204 安装libimobiledevice

libimobiledevice是一个开源的软件&#xff0c;它可以直接使用系统原生协议和IOS设备进行通信&#xff0c;类似iMazing&#xff0c;iTunes&#xff0c;libimobiledevice不依赖IOS的私有库&#xff0c;并且连接IOS设备时用的都是原生协议&#xff0c;IOS无需越狱就能实现设备信息…

贝斯手-MISC-bugku-解题步骤

——CTF解题专栏—— 题目信息&#xff1a; 题目&#xff1a;贝斯手 作者&#xff1a;Tokeii 提示&#xff1a;无 解题附件&#xff1a; 解题思路&信息收集&#xff1a; 详细信息看了&#xff0c;没有藏料&#xff0c;这次上来就是一个命好名的压缩包浅浅打开一下&…

9.整数转换为布尔值【2023.12.1】

1.问题描述 整数转换为布尔值。 2.解决思路 输入一个整数。 输出布尔值并输出。 3.代码实现 numint(input("请输入一个数字")) boolnumbool(num) print(boolnum)4.运行结果

AutoDL 使用记录

AutoDL 使用记录 1.租用新实例 创建实例需要依次选择&#xff1a;计费方式 → \to → 地区 → \to → GPU型号与数量 → \to → 主机 注意事项&#xff1a; 主机 ID&#xff1a;一个吉利的机号有助于炼丹成功价格&#xff1a;哪个便宜选哪个最高 CUDA 版本&#xff1a;影响…

ElasticSearch知识体系详解

1.介绍 ElasticSearch是基于Lucene的开源搜索及分析引擎&#xff0c;使用Java语言开发的搜索引擎库类&#xff0c;并作为Apache许可条款下的开放源码发布&#xff0c;是当前流行的企业级搜索引擎。 它可以被下面这样准确的形容&#xff1a; 一个分布式的实时文档存储&#xf…

API成批分配漏洞介绍与解决方案

一、API成批分配漏洞介绍 批量分配&#xff1a;在API的业务对象或数据结构中&#xff0c;通常存在多个属性&#xff0c;攻击者通过篡改属性值的方式&#xff0c;达到攻击目的。比如通过设置user.is_admin和user.is_manager的值提升用户权限等级&#xff1b;假设某API的默认接口…

SQL Server 数据库,使用函数查询统计信息

4.1 在查询中使用函数 在前面章节已经学习了一些简单的增、删、改、查询的T-SOL.语句&#xff0c;但是为了更方便快捷地完 成大量的任务&#xff0c;SOLServer提供了一些内部函数&#xff0c;可以和SOLServer的SELECT语句联合使用&#xff0c;也可 以与UPDATE和INSERT一起使用&…

scrapy框架

scrapy文档 文档链接 安装指南 — Scrapy 2.5.0 文档 (osgeo.cn)https://www.osgeo.cn/scrapy/intro/install.html 创建scrapy框架 0.介绍&#xff1a; scrapy是异步非阻塞框架 异步&#xff1a;一个主线程有20个任务&#xff0c;可以来回切换 非阻塞&#xff1a;运行的程序不需…

一、服务器准备

本案例使用VMware Workstation Pro虚拟机创建虚拟服务器来搭建Linux服务器集群&#xff0c;所用软件及版本如下&#xff1a; Centos7.7-64bit 1、三台虚拟机创建 第一种方式&#xff1a;通过iso镜像文件来进行安装(不推荐) 第二种方式&#xff1a;直接复制安装好的虚拟机文…

基于springboot + vue框架的网上商城系统

qq&#xff08;2829419543&#xff09;获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;springboot 前端&#xff1a;采用vue技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xf…

电子学会C/C++编程等级考试2021年12月(四级)真题解析

C/C++等级考试(1~8级)全部真题・点这里 第1题:移动路线 桌子上有一个m行n列的方格矩阵,将每个方格用坐标表示,行坐标从下到上依次递增,列坐标从左至右依次递增,左下角方格的坐标为(1,1),则右上角方格的坐标为(m,n)。 小明是个调皮的孩子,一天他捉来一只蚂蚁,不小心把…

TZOJ 1429 小明A+B

答案&#xff1a; #include <stdio.h> int main() {int T0, A0, B0, sum0;scanf("%d", &T); //输入测试数据的组数while (T--) //循环T次{scanf("%d %d", &A, &B); //输入AB的值sum A B;if (sum > 100) //如果是三位数{…

JavaScript 内存泄漏的检测与防范:让你的程序更稳定

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

实施全链路压测的步骤是怎样的?

全链路压测是确保系统稳定性和性能的重要手段&#xff0c;能够帮助企业在面临日益复杂的业务场景时保持竞争力。通过深入了解业务、合理规划测试场景、及时监控系统指标&#xff0c;企业可以更好地利用全链路压测&#xff0c;为系统的稳定运行提供可靠的保障。同时&#xff0c;…