LeetCode每日一题:1094. 拼车

2023.12.2
Problem: 1094. 拼车

思路

方法一:刚好最近在刷优先队列相关的题目,也做到挺多,拿到题目,观察到车沿一个方向前进,那么到每一个地方(from or to)也就有确定的顺序,这个时候我们可以维护一个优先队列,当遇到最小的 from 就压入,此时弹出刚好小于等于 fromto

方法二:AC后刷题解,官方并没给出上述解法,而是差分数组,这也是我第一次听到这个。换个说法,就是前缀和的逆,一般来说是 S[n-1] + A[n] = S[n],这里变成 A[n] = S[n] - S[n-1],那这样的话就很容易理解了,我们先用一个数组 diff[i] 记录第 i 个站的净上下车乘客量,再通过 diff[i] 计算 count[i],当 count[i] > capacity 时,则超载。

解题方法

方法一:优先队列

  • 先对 from 进行升序排序,保证入队时是最小的 from 先入;
  • 增加一个 cnt 记录当前的总乘客数;
  • 扫描 trips,将当前 from 处的 vector 压入优先队列中,弹出当前的等于 fromto,压入时(上车)增加乘客数 cnt,弹出时(下车)减少乘客数 cnt
    (此时的 to 一定能保证最小,因为 to 是从 0~from 依次弹出的,并且车沿一个方向,也就有 to > from
  • cnt 大于 capacity(车容量),则超载,否则成功。

方法二:差分数组

  • 先遍历 trips 计算出 diff,遍历过程中记录一个 to 的最大值 to_max最远的站,便于后续遍历 diffcount
  • 遍历 diffcount ,当 count[i] > capacity 时超载。
    为了简化,我们只需记录 count[i],因为count[i-1]并不会用到,只有当前状态才会用到,因此只需要一个变量 cnt 记录当前通过 diff 得到的前缀和,得到立即判断即可。

复杂度

方法一: O ( n l o g n ) O(nlogn) O(nlogn),其中 n = l e n ( t r i p s ) n=len(trips) n=len(trips)

方法二: O ( n + l ) O(n+l) O(n+l),其中 n = l e n ( t r i p s ) l = m a x ( t r i p s . t o ) n=len(trips)\quad l=max(trips.to) n=len(trips)l=max(trips.to)

Code

// 优先队列
class Solution {
public:
    bool static cmp1(const vector<int> &a,const vector<int> &b) {
        return a[1] < b[1];
    }
    class cmp2 {
        public:
        bool operator()(const vector<int> &a,const vector<int> &b) {
            return a[2] > b[2];
        }
    };

    bool carPooling(vector<vector<int>>& trips, int capacity) {
        sort(trips.begin(), trips.end(), cmp1);
        priority_queue<vector<int>, vector<vector<int>>, cmp2> pq;
        int cap = 0;
        for (int i=0; i<trips.size();i++) {
            while (!pq.empty() && pq.top()[2] <= trips[i][1]) {
                cap -= pq.top()[0];
                pq.pop();
            }
            cap += trips[i][0];
            if (cap > capacity) {
                return false;
            }
            pq.push(trips[i]);
        }
        return true;
    }
};
// 差分数组
class Solution {
public:
    bool carPooling(vector<vector<int>>& trips, int capacity) {
        int diff[1001] = { 0 };
        int to_max = 0, cnt = 0;
        for (auto &t: trips) {
            to_max = max(to_max, t[2]);
            diff[t[1]] += t[0];
            diff[t[2]] -= t[0];
        }
        for (int i=0; i<=to_max; i++) {
            cnt += diff[i];
            if (cnt > capacity) return false;
        }
        return true;
    }
};
  • 24
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YRoads

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值