leetcode_1094 拼车
·
1. 题意
有n段旅程,每段旅程由上车点、下车点、上车人数组成。
求给定的旅程是否能让所有旅程顺利完成。
拼车
2. 题解
首先肯定要将旅程按上车位置进行排序。
2.1 模拟+小根堆
根据下车时间的早晚创建一个小根堆。
在每次进行新的旅程前判断是否有人下车了,即在堆非空情况下,判断最早下车旅程是否小于下一段旅程的起始点。
若有人下车,即将堆顶得到旅程给弹出释放车上的空位,直到堆中无元素或堆顶下车时间大于新旅程的上车时间。
若无人下车或堆空,则判断是否有足够的位置容纳新的旅程。
没有则返回结果,有则插入该旅程并减小容纳位置。
class Solution {
public:
struct trip {
trip( const vector<int> &arr)
{
p = arr[0];
f = arr[1];
t = arr[2];
}
bool operator <(const trip &b) const
{ return t > b.t;}
int p;
int f;
int t;
};
bool carPooling(vector<vector<int>>& trips, int capacity) {
sort(trips.begin(), trips.end(),
[](const vector<int> &a, const vector<int> &b)
{
if ( a[1] == b[1])
return a[2] < b[2];
return a[1] < b[1];
});
priority_queue<trip> pq;
int sz = trips.size();
for (vector<int> &t: trips) {
trip v(t);
while ( !pq.empty() ) {
auto top = pq.top();
if (top.t > v.f)
break;
capacity += top.p;
pq.pop();
}
if ( capacity < v.p )
return false;
capacity -= v.p;
pq.push(v);
}
return true;
}
};
2.2 判断每个位置是否合理+差分
由于我们并不在意实际在哪上下,而只是在意是否能容纳。
我们可以反向考虑每个位置点车上的总人数,如果大于了最大容量则不能完成;
否则可以完成该旅程。
所以可以用一个数组标识每个位置点上的总人数。
添加旅程的时候,将起始点到结束点范围的状态位置更新。
最后再判断是否有位置点超过最大容量即可。
- 简单区间更新
class Solution {
public:
bool carPooling(vector<vector<int>>& trips, int capacity) {
int num[1001]={0};
for (auto &v: trips) {
for (int i = v[1]; i < v[2]; ++i) {
num[i] += v[0];
}
}
for (int i = 0 ; i <= 1000; ++i) {
if ( num[i] > capacity)
return false;
}
return true;
}
};
- 差分
由于这里是区间进行更新相同值,而且我们最终还是要遍历每个点的;所以可以直接使用差分进行更新。
class Solution {
public:
bool carPooling(vector<vector<int>>& trips, int capacity) {
int num[1001]={0};
for (auto &v: trips) {
num[v[1]] += v[0];
num[v[2]] -= v[0];
}
int prefix = 0;
for (int i = 0 ; i <= 1000; ++i) {
prefix += num[i];
if ( prefix > capacity)
return false;
}
return true;
}
};
更多推荐

所有评论(0)