学习记录:js算法(十一):车队

车队

在一条单行道上,有 n 辆车开往同一目的地。目的地是几英里以外的 target 。
给定两个整数数组 position 和 speed ,长度都是 n ,其中 position[i] 是第 i 辆车的位置, speed[i] 是第 i 辆车的速度(单位是英里/小时)。
一辆车永远不会超过前面的另一辆车,但它可以追上去,并以较慢车的速度在另一辆车旁边行驶。
车队 是指并排行驶的一辆或几辆汽车。车队的速度是车队中 最慢 的车的速度。
即便一辆车在 target 才赶上了一个车队,它们仍然会被视作是同一个车队。
返回到达目的地的车队数量 。

示例 1:
输入:target = 12, position = [10,8,0,5,3], speed = [2,4,1,1,3]
输出:3
解释:
从 10(速度为 2)和 8(速度为 4)开始的车会组成一个车队,它们在 12 相遇。车队在 target 形成。
从 0(速度为 1)开始的车不会追上其它任何车,所以它自己是一个车队。
从 5(速度为 1) 和 3(速度为 3)开始的车组成一个车队,在 6 相遇。车队以速度 1 移动直到它到达 target。

示例 2:
输入:target = 10, position = [3], speed = [3]
输出:1
解释:
只有一辆车,因此只有一个车队。

示例 3:
输入:target = 100, position = [0,2,4], speed = [4,2,1]
输出:1
解释:
从 0(速度为 4) 和 2(速度为 2)开始的车组成一个车队,在 4 相遇。从 4 开始的车(速度为 1)移动到了 5。
然后,在 4(速度为 2)的车队和在 5(速度为 1)的车成为一个车队,在 6 相遇。车队以速度 1 移动直到它到达 target。

我的思路:数组循环

var carFleet = function (target, position, speed) {
    const times = [];
    for (let i = 0; i < position.length; i++) {
        times[i] = (target - position[i]) / speed[i];
    }
    position.sort((a, b) => a - b);
    times.sort((a, b) => position[times.indexOf(a)] - position[times.indexOf(b)]);
    let cars = 0;
    let lastTime = 0;
    for (let i = position.length - 1; i >= 0; i--) {
        if (lastTime < times[i]) {
            cars++;
            lastTime = times[i];
        }
    }
    return cars;
};

讲解

  1. 首先得理清思路:每辆车到达终点的时间,是根据 (终点 - 当前距离)/ 速度 得到,然后根据 position 内部距离按从小到大排序,确保从后向前可以正确地比较到达时间。然后就是循环的问题了,考虑到如果从前往后循环,会导致如果一辆车会追上前面的车,可能会在后续的遍历中再次计算这个车队的到达时间,导致重复计数。比如,若 车A车B 合并成一个车队,后续再遇到 车C 时,可能会错误地将 车A 和 车B 的计数再次计算。所以这里就用了从后往前的循环。因为只需要考虑前车即可,所以后一辆车到达目标的时间小于或等于前一辆车的到达时间,代表后车追上前车,形成一个车队。
  2. 创建一个 time(时间数组),用来存储每辆车跑到 target(终点) 需要的时间
  3. 创建一个 cars(新车队数量) 和 lastTime(车子最后到达终点的时间)
  4. 步骤2 的目的:从最后一辆车开始向前遍历,检查每辆车的到达时间。如果当前车的到达时间 time[i] 大于 lastTime,则说明这一辆车会形成一个新的车队,增加车队计数,并更新 lastTime 为当前车的到达时间。

网上思路:使用栈来解决

var carFleet = function (target, position, speed) {
    const n = position.length;
    const times = [];
    for (let i = 0; i < n; i++) {
        times.push((target - position[i]) / speed[i]);
    }
    const cars = position.map((pos, idx) => [pos, times[idx]]).sort((a, b) => b[0] - a[0]);
    const stack = [];
    for (let i = 0; i < n; i++) {
        const time = cars[i][1];
        if (stack.length === 0 || time > stack[stack.length - 1]) {
            stack.push(time);
        }
    }
    return stack.length;
};

讲解

  1. 首先计算每辆车到达目标的时间并存储在 times 数组中。
  2. 然后将位置和时间结合成一个数组 cars,并按位置降序排序。
  3. 使用栈来管理车队:我们从后向前遍历这些车,使用一个栈来存储车队的到达时间。这样可以帮助我们判断当前车是否会与前面的车形成同一车队。如果当前车的到达时间小于或等于栈顶车的到达时间,说明当前车会追上前面的车,形成同一车队。如果当前车的到达时间大于栈顶车的到达时间,说明当前车会单独形成一个新的车队。
  4. 最后返回栈的长度,即为车队的数量。

总结

第一反应还是想着通过循环来解决问题了,没往栈上面想,但是回头看了看这两种思路,其实都是差不多的,核心还是先计算所有车辆到达时间,然后通过排序确保可以正确地比较到达时间。最后就是循环了。万变不离循环~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值