【单调栈】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;
};

【单调栈】LeetCode1776:车队,# 算法题,算法,leetcode,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:车队,# 算法题,算法,leetcode,c++,单调栈,车队,相遇,栈顶文章来源地址https://www.toymoban.com/news/detail-765278.html

到了这里,关于【单调栈】LeetCode1776:车队的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • leetcode 141.环形链表 I - 142.环形链表 II 代码及指针相遇证明问题

    给你一个链表的头节点 head ,判断链表中是否有环。如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 如果链表中存在环 ,则返回 true 。 否则,返回 false 。 思路: 快慢指针问题 。我们可以声明一个 fast 指针(一次走两步),声明一个 slow

    2024年02月12日
    浏览(64)
  • 单调栈【leetcode】

    笔记:代码随想录 单调栈:需要自己维持顺序,没有现成容器可以用。 1.每日温度 单调栈使用规则: 通常是一维数组,要寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置,此时我们就要想到可以用单调栈了 。时间复杂度为O(n)。空间复杂度O(n)。 本质:空

    2024年02月03日
    浏览(31)
  • leetcode:每日温度---单调栈

    给定一个整数数组  temperatures  ,表示每天的温度,返回一个数组  answer  ,其中  answer[i]  是指对于第  i  天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用  0  来代替。 示例 1: 示例 2: 示例 3: 提示: 1 = temperatures.length = 105 30 = temperatur

    2024年01月25日
    浏览(56)
  • LeetCode 热题100——单调栈

    ​   个人主页: 日刷百题 系列专栏 : 〖C语言小游戏〗 〖Linux〗 〖数据结构〗   〖C语言〗 🌎 欢迎各位 → 点赞 👍+ 收藏 ⭐️+ 留言 📝  ​ ​ 递增单调栈:栈中元素从栈底到栈顶依次增大 递减单调栈:栈中元素从栈底到栈顶依次减小 在学习完朴素的数据结构栈之后,

    2024年02月04日
    浏览(41)
  • leetcode739. 每日温度 单调栈

    自己思路: 想到用两个栈,一个维护元素、另一个维护下标。但是还是无法处理有重复元素的问题(用哈希表来存储的时候)。所以就看了答案的思路。 答案思路: 从前往后遍历,维护一个单调栈。栈存放数组的下标。 ①栈为空 or 当前下标元素 = 栈顶元素,入栈; ②当前

    2024年02月11日
    浏览(32)
  • LeetCode42.接雨水(单调栈)

    给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 思路: 从题目中我们可以知道:只有凹陷的地方才可以存储雨水,那么高度一定是先减后增,所以当我们遍历到 增 这个位置时,前面减的地方(即凹陷的地方)一定会存储

    2024年02月21日
    浏览(35)
  • leetcode 738. 单调递增的数字

             这题用暴力法会超时,我就没试了,采用了个挺巧的方法,为了方便需要先将整数n转换为字符串的形式,然后从后向前遍历,当两个数字非递增时,将前一个数字--,后一个数字的位置记录在index中,之后需要将这个index以后的数字全赋为9。  为了防止将不需要赋

    2024年02月14日
    浏览(36)
  • 【Leetcode】 738. 单调递增的数字

    当且仅当每个相邻位数上的数字 x 和 y 满足 x = y 时,我们称这个整数是 单调递增 的。 给定一个整数 n ,返回 小于或等于 n 的最大数字,且数字呈 单调递增 。 示例 1 : 输入 : n = 10 输出 : 9 示例 2 : 输入 : n = 1234 输出 : 1234 示例3 : 输入 : n = 332 输出 : 299 提示: AC : 需要注意的点

    2024年02月07日
    浏览(37)
  • Leetcode刷题笔记——单调性

    单调性是数学中使用的一种常见性质,通常用于描述函数,在高等数学中的定义常常为: 设函数f(x)在区间I上有定义,如果对于I上的任意两个数x1和x2,当x1x2时,有f(x1)f(x2)(或者f(x1)f(x2)),则称函数f(x)在区间I上是单调递增的(或者单调递减的)。 例如如下图像就是两个单

    2024年02月11日
    浏览(35)
  • 【Leetcode】接雨水(双指针、单调栈)

    目录 💡题目描述 💡双指针解法 💡单调栈解法 给定  n  个非负整数表示每个宽度为  1  的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 提示: n == height.length 1 = n = 2 * 104 0 = height[i] = 105 思路: 假设 每个宽度为1的柱子那里有 一个高度未知的宽度为1的水

    2024年01月21日
    浏览(66)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包