【单调栈】LeetCode1776:车队

2023-12-20 08:04
文章标签 单调 车队 leetcode1776

本文主要是介绍【单调栈】LeetCode1776:车队,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

作者推荐

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

涉及知识点

单调栈

题目

在一条单车道上有 n 辆车,它们朝着同样的方向行驶。给你一个长度为 n 的数组 cars ,其中 cars[i] = [positioni, speedi] ,它表示:
positioni 是第 i 辆车和道路起点之间的距离(单位:米)。题目保证 positioni < positioni+1 。
speedi 是第 i 辆车的初始速度(单位:米/秒)。
简单起见,所有车子可以视为在数轴上移动的点。当两辆车占据同一个位置时,我们称它们相遇了。一旦两辆车相遇,它们会合并成一个车队,这个车队里的车有着同样的位置和相同的速度,速度为这个车队里 最慢 一辆车的速度。
请你返回一个数组 answer ,其中 answer[i] 是第 i 辆车与下一辆车相遇的时间(单位:秒),如果这辆车不会与下一辆车相遇,则 answer[i] 为 -1 。答案精度误差需在 10^-5 以内。
示例 1:
输入:cars = [[1,2],[2,1],[4,3],[7,2]]
输出:[1.00000,-1.00000,3.00000,-1.00000]
解释:经过恰好 1 秒以后,第一辆车会与第二辆车相遇,并形成一个 1 m/s 的车队。经过恰好 3 秒以后,第三辆车会与第四辆车相遇,并形成一个 2 m/s 的车队。
示例 2:
输入:cars = [[3,4],[5,4],[6,3],[9,1]]
输出:[2.00000,1.00000,1.50000,-1.00000]
提示:
1 <= cars.length <= 105
1 <= position_{i} , speed_{i} <= 106
positioni < positioni+1

单调栈

车队的前后和数组的前后相反,按车队从前到后枚举i(i从大到小)。
有如下规律:
一,车队的第一辆车不会降速。所以相遇的时候只考虑车队头。
二,前面的车比当前车块,则不会被当前车追上。
三,一辆车在被追上前,追上前面的车。则不会成为车队头。
四,后面的车不能越过当前车,可以将二三的"当前车"扩大为"当前车及后面的车"。即情况二三的车被淘汰。
五,除栈顶的车外,都有可能成为车头,否则早被淘汰了。

规则二,使得前面速度快的车被淘汰,于是栈中的速度升序,形成单调栈

代码

核心代码

class Solution {
public:vector<double> getCollisionTimes(vector<vector<int>>& cars) {m_c = cars.size();vector<double> vRet(m_c, -1);stack<int> staIndex;for (int i = m_c - 1; i >= 0; i--){while (staIndex.size() && (cars[staIndex.top()][1] >= cars[i][1])){//淘汰速度快的车,当前车追不上。后面的车也追不上staIndex.pop();}
#define MeetTime (((double)cars[staIndex.top()][0] - cars[i][0]) / (cars[i][1] - cars[staIndex.top()][1]))auto MeetPre = [&]() {if (staIndex.empty() || (vRet[staIndex.top()] < 0)){return false;}return MeetTime >= vRet[staIndex.top()];};while (MeetPre()){//淘汰被追上前,就追上前面的车staIndex.pop();}if (staIndex.size()){vRet[i] = MeetTime;}staIndex.emplace(i);}return vRet;}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<vector<int>> cars;{Solution slu;cars = { {1,2},{2,1},{4,3},{7,2} };auto res = slu.getCollisionTimes(cars);Assert({ 1.00000,-1.00000,3.00000,-1.00000 }, res);}{Solution slu;cars = { {3,4},{5,4},{6,3},{9,1} };auto res = slu.getCollisionTimes(cars);Assert({ 2.00000,1.00000,1.50000,-1.00000 }, res);}//CConsole::Out(res);
}

2023年3月版

class Solution {
public:
vector getCollisionTimes(vector<vector>& cars) {
m_c = cars.size();
vector vRet(m_c, -1);
std::stack sta;//碰撞时,可能的出头
sta.push(m_c - 1);
for (int i = m_c - 1 - 1; i >= 0; i–)
{
while (sta.size())
{
const int iPre = sta.top();
if (cars[i][1] <= cars[iPre][1])
{//速度慢或相等,永远无法撞上
sta.pop();
}
else
{
const double dMeetTime = (double)(cars[iPre][0] - cars[i][0]) / (cars[i][1] - cars[iPre][1]);
if ((vRet[sta.top()] > 0 ) && (dMeetTime >= vRet[iPre]))
{
sta.pop();
}
else
{
break;
}
}
}
if (sta.size())
{
const int iPre = sta.top();
const double dMeetTime = (double)(cars[iPre][0] - cars[i][0]) / (cars[i][1] - cars[iPre][1]);
vRet[i] = dMeetTime;
}
else
{
vRet[i] = -1;
}
sta.push(i);
}
return vRet;
}
int m_c;
};

2023年7月版

class Solution {
public:
vector getCollisionTimes(vector<vector>& cars) {
m_c = cars.size();
std::stack sta;
sta.emplace(m_c - 1);
vector vRet(m_c, -1);
for (int i = m_c - 2; i >= 0; i–)
{
//确保栈顶元素是相撞的车,两个条件:一,此车不能快于当前车 二,此车不能被撞之前撞上其它车
#define CurCar cars[i]
#define PreCar cars[sta.top()]
#define MeetTime ((double)PreCar[0] - CurCar[0])/(CurCar[1] - PreCar[1])
#define NeedMove1 (CurCar[1] <= PreCar[1])
#define NeedMove2 (vRet[sta.top()] > 1e-9) && ( MeetTime > vRet[sta.top()])
while (sta.size() && (NeedMove1 || NeedMove2))
{
sta.pop();
}
vRet[i] = sta.size() ? MeetTime : -1;
sta.push(i);
}
return vRet;
}
int m_c;
};

2023年9月版

class Solution {
public:
vector getCollisionTimes(vector<vector>& cars) {
m_c = cars.size();
vector vRet(m_c,-1);
std::stack sta;
for (int i = m_c - 1; i >= 0; i–)
{
while (sta.size())
{
int pre = sta.top();
if (cars[i][1] - cars[pre][1] <= 0)
{
sta.pop();
}
else
{
double dMeet = (cars[pre][0] - cars[i][0]) / (double)(cars[i][1] - cars[pre][1]);
if ((abs(vRet[pre] + 1) < 0.0001) || (dMeet < vRet[pre]))
{
vRet[i] = dMeet;
break;
}
else
{
sta.pop();
}
}
}
sta.emplace(i);
}
return vRet;
}
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**
如无特殊说明,本算法C++ 实现。

这篇关于【单调栈】LeetCode1776:车队的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/515301

相关文章

POJ1631最长单调递增子序列

最长单调递增子序列 import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;import java.math.BigInteger;import java.util.StringTokenizer;publ

力扣 739. 每日温度【经典单调栈题目】

1. 题目 理解题意: 1.1. 给一个温度集合, 要返回一个对应长度的结果集合, 这个结果集合里面的元素 i 是 当前 i 位置的元素的下一个更高温度的元素的位置和当前 i 位置的距离之差, 若是当前元素不存在下一个更高温度的元素, 则这个位置用0代替; 2. 思路 本题用单调栈来求解;单调栈就适用于来求当前元素左边或者右边第一个比当前元素大或者小的元素;【单调栈:让栈中的元素保持单调

双指针(5)_单调性_有效三角形的个数

个人主页:C++忠实粉丝 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C++忠实粉丝 原创 双指针(5)_单调性_有效三角形的个数 收录于专栏【经典算法练习】 本专栏旨在分享学习C++的一点学习笔记,欢迎大家在评论区交流讨论💌 目录 1. 题目链接: 2.题目描述 : 3.解法 :     解法一(暴力枚举) :     算法思路 :     代码展示 : 暴力枚

机器学习模型中的因果关系:引入单调约束

单调约束是使机器学习模型可行的关键,但它们仍未被广泛使用欢迎来到雲闪世界。 碳ausality 正在迅速成为每个数据科学家工具包中必不可少的组成部分。 这是有充分理由的。 事实上,因果模型在商业中具有很高的价值,因为它们为“假设”情景提供了更可靠的估计,特别是在用于做出影响业务结果的决策时。 在本文中,我将展示如何通过简单的更改(实际上添加一行代码)将传统的 ML 模型(如随机森林、L

史上最贵婚车队 劳斯莱斯幻影兰博基尼法拉利扎堆

史上最贵婚车队 劳斯莱斯幻影兰博基尼法拉利扎堆

单调栈的实现

这是C++算法基础-数据结构专栏的第二十四篇文章,专栏详情请见此处。 引入         单调栈就是满足单调性的栈结构,它最经典的应用就是给定一个序列,找出每个数左边离它最近的比它大/小的数。         下面我们就来讲单调栈的实现。 定义          单调栈就是满足单调性的栈结构,也就是说,其中的元素具有单调性,但是存储的方法和基本操作与栈一样。 过

单调队列(专项复习)

P1886 滑动窗口 /【模板】单调队列    题目思路:单调队列模版题,每次都输出队列中的第一个元素。以此维护队列中元素序号的单调性,得到结果。只是比较判断,时间复杂度很小。相等的值也要挤掉。最大值同理。 代码实现: #include<bits/stdc++.h>using namespace std;typedef long long ll;#define N 3000005

【每日一题】LeetCode 84.柱状图中最大的矩形(栈、数组、单调栈)

【每日一题】LeetCode 84.柱状图中最大的矩形(栈、数组、单调栈) 题目描述 给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。求在该柱状图中,能够勾勒出来的矩形的最大面积。 这个题目和接雨水非常类似 点击跳转接雨水 LeetCode 40.接雨水 输入示例 输入:heights = [2,1,5,6,2,3] 输出:10 解释:最大的

[算法]单调栈解法

目录 739. 每日温度 - 力扣(LeetCode)  42. 接雨水 - 力扣(LeetCode) 84. 柱状图中最大的矩形 - 力扣(LeetCode) 739. 每日温度 - 力扣(LeetCode)  解法: 通常是一维数组,要寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置,此时我们就要想到可以用单调栈了。 1.在本题中,其实就是,找到一个元素右边

力扣刷题单调栈

单调栈 No.1 739.每日温度. - 力扣(LeetCode) 给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用 0 来代替。 示例 1: 输入: temperatures = [73,74,75,71,69,72,76,7