[python 刷题] 853 Car Fleet
哎……周赛第三题解应该用 monotonic stack 做优化的,没写出来,所以多刷两题 monotonic stack 的题目找找感觉……
题目:
There are
n
cars going to the same destination along a one-lane road. The destination istarget
miles away.You are given two integer array
position
andspeed
, both of lengthn
, whereposition[i]
is the position of theith
car andspeed[i]
is the speed of theith
car (in miles per hour).A car can never pass another car ahead of it, but it can catch up to it and drive bumper to bumper at the same speed. The faster car will slow down to match the slower car’s speed. The distance between these two cars is ignored (i.e., they are assumed to have the same position).
A car fleet is some non-empty set of cars driving at the same position and same speed. Note that a single car is also a car fleet.
If a car catches up to a car fleet right at the destination point, it will still be considered as one car fleet.
Return the number of car fleets that will arrive at the destination.
如果车碰撞在一起的话,就会融合成一个 cluster,这题问的是到了终点后会有几个 cluster
几个核心重点是:
- 所有车共用一条道
- 永远不可能超车
- 后车撞到前车,后车速会降到前车的速度
- 两车之间没有间距
以第一个例子 target = 12, position = [10,8,0,5,3], speed = [2,4,1,1,3]
来说,图解大概是这个样子的:
图解其实能够比较明显的看出有几个 cluster
这道题的一个解法是使用 monotonic stack 去做,思路大致如下:
-
构成
[position, time]
的配对 -
对
position
使用降序排序因为有一个
target
的限制,所以这道题会出现这两种情况:-
两辆车会在抵达 target 之前/之时相遇
这也就意味着初始位置较小的那一条在 0 < = t < = t a r g e t 0 <= t <= target 0<=t<=target 这个时间段之间会遇到初始位置较大的那一条
这个时候,初始位置较大的那辆车相当于作为距离和速度的上限,两辆车相遇后即可合并为一个 cluster,并且依旧以初始位置较大且速度较慢的那辆车作为上限
其原因就在于
后车撞到前车,后车速会降到前车的速度
这条限制,换言之,一旦相遇后,两辆车其实就可以视为一辆车 -
两条线不会在抵达 target 之前/之时相遇
这种情况到下一步处理
-
-
完成了之后就可以对抵达速度使用 monotonic stack 进行追溯,这个时候只需要保留抵达时间耗时较久(速度较慢)的那条即可
依旧以上面的案例进行解释,将其进行排序后的结果为:
[(10, 2), (8, 4), (5, 1), (3, 3), (0, 1)]
-
第一辆车抵达终点的时间为
1.0
-
第二辆车抵达终点的时间也为
1.0
这时候可以讲两辆车的抵达时间合并,并且取第一辆的抵达时间
主要原因也是因为在初始距离较大,初始速度较慢,在抵达最终距离前/时被追上,一定意味着后车抵达最终距离的耗时 < = <= <= 前车
-
第三辆抵达终点位置的时间为
7.0
这时候它与前车不相交,因此自成一个 cluster
-
重复当前操作一直到遍历完所有车
-
使用 LC 上提供的第三个案例相对而言会更直接一些:
target = 100, position = [0,2,4], speed = [4,2,1]
代码如下:
class Solution:
def carFleet(self, target: int, position: List[int], speed: List[int]) -> int:
# store (speed, pos) pair
pair = [(p, s) for p, s in zip(position, speed)]
stack = []
pair.sort(reverse = True)
for p, s in pair:
stack.append((target - p) / s)
print((target - p) / s)
if len(stack) >= 2 and stack[-1] <= stack[-2]:
stack.pop()
return len(stack)