Skip to content

Latest commit

 

History

History
192 lines (154 loc) · 6.23 KB

File metadata and controls

192 lines (154 loc) · 6.23 KB
comments difficulty edit_url rating source tags
true
困难
2530
第 230 场周赛 Q4
数组
数学
单调栈
堆(优先队列)

English Version

题目描述

在一条单车道上有 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 <= positioni, speedi <= 106
  • positioni < positioni+1

解法

方法一:栈

由于每一辆车最终追上其右边第一辆车的时间与其左边的车没有关系,因此,我们可以从右往左遍历,计算每辆车与其右边第一辆车相遇的时间。

具体地,我们维护一个栈,栈中存放的是车辆的编号,栈顶元素表示当前最慢的车辆编号,栈底元素表示当前最快的车辆编号。

当我们遍历到第 $i$ 辆车时,如果第 $i$ 辆车的速度大于栈顶元素对应的车辆 $j$ 的速度,此时我们计算两车相遇的时间,记为 $t$。如果车辆 $j$ 与右边车辆不会相遇,或者 $t$ 小于等于 $j$ 与右辆车相遇的时间,说明车辆 $i$ 可以在 $t$ 时间追上车辆 $j$,更新答案。否则,说明车辆 $i$ 不会与车辆 $j$ 相遇,我们将车辆 $j$ 出栈,继续判断车辆 $i$ 与栈顶元素对应的车辆相遇的时间。如果栈为空,说明车辆 $i$ 不会与任何车辆相遇,更新答案为 $-1$。最后,将车辆 $i$ 入栈。

遍历完所有车辆后,即可得到答案。

时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为车辆数量。

Python3

class Solution:
    def getCollisionTimes(self, cars: List[List[int]]) -> List[float]:
        stk = []
        n = len(cars)
        ans = [-1] * n
        for i in range(n - 1, -1, -1):
            while stk:
                j = stk[-1]
                if cars[i][1] > cars[j][1]:
                    t = (cars[j][0] - cars[i][0]) / (cars[i][1] - cars[j][1])
                    if ans[j] == -1 or t <= ans[j]:
                        ans[i] = t
                        break
                stk.pop()
            stk.append(i)
        return ans

Java

class Solution {
    public double[] getCollisionTimes(int[][] cars) {
        int n = cars.length;
        double[] ans = new double[n];
        Arrays.fill(ans, -1.0);
        Deque<Integer> stk = new ArrayDeque<>();
        for (int i = n - 1; i >= 0; --i) {
            while (!stk.isEmpty()) {
                int j = stk.peek();
                if (cars[i][1] > cars[j][1]) {
                    double t = (cars[j][0] - cars[i][0]) * 1.0 / (cars[i][1] - cars[j][1]);
                    if (ans[j] < 0 || t <= ans[j]) {
                        ans[i] = t;
                        break;
                    }
                }
                stk.pop();
            }
            stk.push(i);
        }
        return ans;
    }
}

C++

class Solution {
public:
    vector<double> getCollisionTimes(vector<vector<int>>& cars) {
        int n = cars.size();
        vector<double> ans(n, -1.0);
        stack<int> stk;
        for (int i = n - 1; ~i; --i) {
            while (stk.size()) {
                int j = stk.top();
                if (cars[i][1] > cars[j][1]) {
                    double t = (cars[j][0] - cars[i][0]) * 1.0 / (cars[i][1] - cars[j][1]);
                    if (ans[j] < 0 || t <= ans[j]) {
                        ans[i] = t;
                        break;
                    }
                }
                stk.pop();
            }
            stk.push(i);
        }
        return ans;
    }
};

Go

func getCollisionTimes(cars [][]int) []float64 {
	n := len(cars)
	ans := make([]float64, n)
	for i := range ans {
		ans[i] = -1.0
	}
	stk := []int{}
	for i := n - 1; i >= 0; i-- {
		for len(stk) > 0 {
			j := stk[len(stk)-1]
			if cars[i][1] > cars[j][1] {
				t := float64(cars[j][0]-cars[i][0]) / float64(cars[i][1]-cars[j][1])
				if ans[j] < 0 || t <= ans[j] {
					ans[i] = t
					break
				}
			}
			stk = stk[:len(stk)-1]
		}
		stk = append(stk, i)
	}
	return ans
}