算法--坐上公交的最晚时间

183 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第15天,点击查看活动详情

题目

leetcode 2332. 坐上公交的最晚时间 难度:困难

给你一个下标从 0 开始长度为 n 的整数数组 buses ,其中 buses[i] 表示第 i 辆公交车的出发时间。同时给你一个下标从 0 开始长度为 m 的整数数组 passengers ,其中 passengers[j] 表示第 j 位乘客的到达时间。所有公交车出发的时间互不相同,所有乘客到达的时间也互不相同。

给你一个整数 capacity ,表示每辆公交车 最多 能容纳的乘客数目。

每位乘客都会搭乘下一辆有座位的公交车。如果你在 y 时刻到达,公交在 x 时刻出发,满足 y <= x  且公交没有满,那么你可以搭乘这一辆公交。最早 到达的乘客优先上车。

返回你可以搭乘公交车的最晚到达公交站时间。你 不能 跟别的乘客同时刻到达。

注意:数组 buses 和 passengers 不一定是有序的。

 

示例 1:

输入:buses = [10,20], passengers = [2,17,18,19], capacity = 2
输出:16
解释:
第 1 辆公交车载着第 1 位乘客。
第 2 辆公交车载着你和第 2 位乘客。
注意你不能跟其他乘客同一时间到达,所以你必须在第二位乘客之前到达。

示例 2:

输入:buses = [20,30,10], passengers = [19,13,26,4,25,11,21], capacity = 2
输出:20
解释:
第 1 辆公交车载着第 4 位乘客。
第 2 辆公交车载着第 6 位和第 2 位乘客。
第 3 辆公交车载着第 1 位乘客和你。
 

提示:

n == buses.length

m == passengers.length

1 <= n, m, capacity <= 105

2 <= buses[i], passengers[i] <= 109

buses 中的元素 互不相同 。

passengers 中的元素 互不相同 。

题解

排序后,用双指针模拟乘客上车的过程:遍历公交车,找哪些乘客可以上车(先来先上车)。

模拟结束后:

如果最后一班公交还有空位,我们可以在发车时到达公交站,如果此刻有人,我们可以顺着他往前找到没人到达的时刻; 如果最后一班公交没有空位,我们可以找到上一个上车的乘客,顺着他往前找到一个没人到达的时刻。 这里可以「插队」的理由是,如果一个乘客上了车,那么他前面的乘客肯定也上了车(因为先来先上车)。

/**
 * @param {number[]} buses
 * @param {number[]} passengers
 * @param {number} capacity
 * @return {number}
 */
var latestTimeCatchTheBus = function(buses, passengers, capacity) {
    let map = {};
    for (let i = 0; i < passengers.length; i++) {
        map[passengers[i]] = true;
    }
    buses = buses.sort((a,b) => a -b);
    
    function helper(index) {
        let arr = passengers.slice();
        arr.push(index);
        arr = [...new Set(arr)];
        arr.sort((a,b) => a - b);
        let num = 0;
        let carIndex = 0;
        for (let i = 0; i < arr.length; ) {
            if (carIndex >= buses.length) break;
            if (arr[i] <= buses[carIndex]) {
                if (num < capacity) {
                    if (arr[i] == index) return true;
                    i++;
                    num++;
                } else {
                    carIndex++;
                    num = 0
                }
            } else {
                carIndex++;
                num = 0
            }
        }
        return false;
    }
    let l = 1;
    let r = 10 ** 9 + 1;
    while (l < r) {
        let mid = Math.floor((l + r) / 2);
        if (helper(mid)) {
            l = mid + 1;
        } else {
            r = mid;
        }
    }
    let ret = r - 1;
    while (map[ret]) {
        ret --;
    }
    return ret;
};

代码详解

题目要求我们赶上最后一班车,那么我们就不需要管最后一辆车之前的其他车什么情况,我们只要知道最后一班车来之前车站还有多少人在等车即可,然后根据这车能做多少人(capacity),选择一个位于capacity位到之前的一个合适的时间,关于这个合适的时间,存在以下几种情况 1、车站等最后一辆车的人数 < capacity,也就是说还有起码一个空位置,那么此时最晚到达时间就是车到的时间buses[busesSize-1] 2、车站等车的人 >= capacity,那么此时最晚到达的时间为车站等车人中第capacity之前一个

题目条件是数组并没有升序,所以先将两个数组升序处理。 上述提到一个车站等车人数,那就申请一个数组空间保存车站等车人数,那我们申请一个多大的呢,当然是capacity,因为我们只需要最后一班车车站等人人数的前capacity,后面的人就算我不来,他们也上不去车。 遍历整个车数组,对所有车发车,当为最后一辆车时保存最后一辆车的情况 然后从数组中寻找合适的位置 题目还有一个条件,必须时间不同,当我们寻找最晚时间后,需要遍历这个时间之前的所有等车人,如果有重复的,我们就提前一分钟