本文已参与「新人创作礼」活动,一起开启掘金创作之路。
一、题目描述:
1094. 拼车 - 力扣(LeetCode) (leetcode-cn.com)
车上最初有 capacity 个空座位。车 只能 向一个方向行驶(也就是说,不允许掉头或改变方向)
给定整数 capacity 和一个数组 trips , trip[i] = [numPassengersi, fromi, toi] 表示第 i 次旅行有 numPassengersi 乘客,接他们和放他们的位置分别是 fromi 和 toi 。这些位置是从汽车的初始位置向东的公里数。
当且仅当你可以在所有给定的行程中接送所有乘客时,返回 true,否则请返回 false。
示例 1:
输入:trips = [[2,1,5],[3,3,7]], capacity = 4
输出:false
示例 2:
输入:trips = [[2,1,5],[3,3,7]], capacity = 5
输出:true
提示:
- 1 <= trips.length <= 1000
- trips[i].length == 3
- 1 <= numPassengersi <= 100
- 0 <= fromi < toi <= 1000
- 1 <= capacity <= 10^5
二、思路分析:
题解中之所以很多人使用辅助数组,是因为旅程的时间差为级别
如果给出一组数据[1,1,10000000],capacity=1;这样就没法使用辅助数组了,必定会TLE,只能老老实实使用模拟
模拟的算法如下(贪心的思想)
- 将一个trip构造一个结构体
- 将这些trip按照开始时间进行从小到大排序(正常的模拟上车)
- 使用一个优先级队列,来存储已经上车的trip(按照下车时间从小到大排序,因为和要来的trip比较的时候,来出队模拟下车的情景)
- 遍历每个trip,比较当前trips的开始时间和优先级队列队首元素的结束时间
- 如果比结束时间大说明队列中有需要下车的,重复4
- 否则,将当前trip入队。
- 出队入队过程中判断是否capacity的合理性。
三、AC 代码:
class Solution {
public:
struct iterm{
int value;
int start;
int end;
iterm(int v,int s,int e):value(v),start(s),end(e){};
bool operator < (const iterm& rhs) const{
return start<rhs.start;
}
};
struct cmp{
bool operator ()(const iterm& a,const iterm& b){
return a.end>b.end;
}
};
bool carPooling(vector<vector<int>>& trips, int capacity) {
vector<iterm> helper;
int n=trips.size();
if(n==0) return true;
for(auto it:trips){
helper.emplace_back(it[0],it[1],it[2]);
}
sort(helper.begin(),helper.end());
priority_queue<iterm,vector<iterm> ,cmp> que;
for(int i=0;i<n;i++){
while(!que.empty()&&que.top().end<=helper[i].start){
capacity+=que.top().value;
que.pop();
}
capacity-=helper[i].value;
que.push(helper[i]);
if(capacity<0) return false;
}
return true;
}
};