Medium
题目描述
有一家餐厅只有一位厨师。给你一个数组 customers,其中 customers[i] = [arrivali, timei]:
- arrivali 是第 i 位顾客的到达时间。到达时间按非递减顺序排序。
- timei 是为第 i 位顾客准备订单所需的时间。
当顾客到达时,他会向厨师下订单,厨师在空闲时开始准备。顾客会等到厨师完成他的订单。厨师不会同时为多个顾客准备食物。厨师按照输入中给出的顺序为顾客准备食物。
返回所有顾客的平均等待时间。与实际答案在 10^-5 范围内的解决方案被认为是正确的。
示例 1:
输入:customers = [[1,2],[2,5],[4,3]]
输出:5.00000
解释:
1) 第一位顾客在时间 1 到达,厨师立即在时间 1 接受订单并开始准备,在时间 3 完成,所以第一位顾客的等待时间是 3 - 1 = 2。
2) 第二位顾客在时间 2 到达,厨师在时间 3 接受订单并开始准备,在时间 8 完成,所以第二位顾客的等待时间是 8 - 2 = 6。
3) 第三位顾客在时间 4 到达,厨师在时间 8 接受订单并开始准备,在时间 11 完成,所以第三位顾客的等待时间是 11 - 4 = 7。
所以平均等待时间 = (2 + 6 + 7) / 3 = 5。
示例 2:
输入:customers = [[5,2],[5,4],[10,3],[20,1]]
输出:3.25000
解释:
1) 第一位顾客在时间 5 到达,厨师立即在时间 5 接受订单并开始准备,在时间 7 完成,所以第一位顾客的等待时间是 7 - 5 = 2。
2) 第二位顾客在时间 5 到达,厨师在时间 7 接受订单并开始准备,在时间 11 完成,所以第二位顾客的等待时间是 11 - 5 = 6。
3) 第三位顾客在时间 10 到达,厨师在时间 11 接受订单并开始准备,在时间 14 完成,所以第三位顾客的等待时间是 14 - 10 = 4。
4) 第四位顾客在时间 20 到达,厨师立即在时间 20 接受订单并开始准备,在时间 21 完成,所以第四位顾客的等待时间是 21 - 20 = 1。
所以平均等待时间 = (2 + 6 + 4 + 1) / 4 = 3.25。
约束条件:
- 1 <= customers.length <= 10^5
- 1 <= arrivali, timei <= 10^4
- arrivali <= arrivali+1
解题思路
这道题目考查的是模拟问题,需要模拟厨师处理订单的过程。
核心思路:
我们需要跟踪厨师当前完成订单的时间,对于每个顾客,计算他们的等待时间。
算法步骤:
- 维护一个变量
currentTime表示厨师完成当前所有订单的时间 - 遍历每个顾客:
- 如果厨师在顾客到达前就空闲了(
currentTime <= arrival),那么厨师可以立即开始准备,开始时间就是顾客到达时间 - 如果厨师仍在忙碌(
currentTime > arrival),那么顾客需要等待到厨师完成前面的订单 - 计算完成时间:开始时间 + 准备时间
- 等待时间 = 完成时间 - 到达时间
- 如果厨师在顾客到达前就空闲了(
- 累计所有等待时间,最后计算平均值
关键点:
- 厨师的开始时间是
max(currentTime, arrival) - 完成时间是开始时间加上准备时间
- 等待时间是完成时间减去到达时间
这个算法的时间复杂度是 O(n),空间复杂度是 O(1),是最优解法。
代码实现
class Solution {
public:
double averageWaitingTime(vector<vector<int>>& customers) {
long long totalWaitTime = 0;
int currentTime = 0;
for (const auto& customer : customers) {
int arrival = customer[0];
int cookTime = customer[1];
// 厨师开始准备的时间
int startTime = max(currentTime, arrival);
// 完成时间
int finishTime = startTime + cookTime;
// 等待时间
int waitTime = finishTime - arrival;
totalWaitTime += waitTime;
currentTime = finishTime;
}
return (double)totalWaitTime / customers.size();
}
};
class Solution:
def averageWaitingTime(self, customers: List[List[int]]) -> float:
total_wait_time = 0
current_time = 0
for arrival, cook_time in customers:
# 厨师开始准备的时间
start_time = max(current_time, arrival)
# 完成时间
finish_time = start_time + cook_time
# 等待时间
wait_time = finish_time - arrival
total_wait_time += wait_time
current_time = finish_time
return total_wait_time / len(customers)
public class Solution {
public double AverageWaitingTime(int[][] customers) {
long totalWaitTime = 0;
int currentTime = 0;
foreach (var customer in customers) {
int arrival = customer[0];
int cookTime = customer[1];
// 厨师开始准备的时间
int startTime = Math.Max(currentTime, arrival);
// 完成时间
int finishTime = startTime + cookTime;
// 等待时间
int waitTime = finishTime - arrival;
totalWaitTime += waitTime;
currentTime = finishTime;
}
return (double)totalWaitTime / customers.Length;
}
}
var averageWaitingTime = function(customers) {
let totalWaitTime = 0;
let currentTime = 0;
for (const [arrival, cookTime] of customers) {
// 厨师开始准备的时间
const startTime = Math.max(currentTime, arrival);
// 完成时间
const finishTime = startTime + cookTime;
// 等待时间
const waitTime = finishTime - arrival;
totalWaitTime += waitTime;
currentTime = finishTime;
}
return totalWaitTime / customers.length;
};
复杂度分析
| 复杂度类型 | 大小 | 说明 |
|---|---|---|
| 时间复杂度 | O(n) | 需要遍历所有顾客一次 |
| 空间复杂度 | O(1) | 只使用常数额外空间 |