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;
    }
};

你可能感兴趣的:(leetcode,堆,leetcode,算法,职场和发展)