LeetCode-1094. 拼车(JavaScript-差分数组解法)

1,361 阅读2分钟

题目链接:leetcode-cn.com/problems/ca…

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7938be1935d54a84ba2ce6ccd2a26787~tplv-k3u1fbpfcp-zoom-1.image

解法:差分数组

前面讲了 前缀和 的方法,利用 前缀和 ,可以得到数组中 num[i] ... nums[j] 任意区间的累加和

而利用 差分数组,可以实现对数据的某个区间段进行频繁的操作,如加减乘除

1、差分数组是啥

题目给的数组 nums

定义一个差分数组 diff

diff[0] = nums[0]

diff[i] = nums[i] - nums[i-1]

差分数组的第 i 项,就是 numsi 项与前一项之差

2、差分数组能干啥

作用:可以实现对 nums 数组的某个区间段进行频繁操作,加减乘除

怎么得出这个结论的呢?

diff[i] = nums[i] - nums[i-1]

那么 nums[i] = diff[i] + nums[i-1]

又因为 diff[0] === nums[0]

那么在已知差分数组的情况下,可以推断出 nums 数组

假如要对闭区间 nums[left]nums[right] 的值都加 2

可以转成:将 left 及之后的值都加 2 ⇒ ``,然后再将 right 之后的值减 2

这样就实现了在 leftright 的区间内加 2 的操作

num[left] + 2 = diff[left] - nums[left - 1] + 2
num[right] - 2 = diff[right] - nums[right - 1] - 2

nums[left] 操作转化为对 diff[left] 操作

对闭区间 nums[left] ... nums[right] 都加 2 转为

diff[left] + 2,然后 diff[right] - 2

所以我们解题的思路就是根据题意找到初始的 nums,然后根据 nums 构造一个差分数组 diff ,然后利用 diff 替代 nums 进行频繁操作,最后根据 diff 生成最新的 nums

本题思路:

1、找到初始 nums

先根据题意,找到初始的 nums ,这里是一个初始全为 0 的数组

每个 0 代表在每个地点的乘客数,初始没有乘客

2、构造 diff

再根据 nums ,构造 diff

再根据题意 0 <= trips[i][1] < trips[i][2] <= 1000

numsdiff 的长度都设为 1000

3、将题意转化为对 nums 的操作

上车 n 人,代表 [left, right)区间,都 + n

下车 n 人,代表 [left, right)区间,都 - n

注意, left是闭区间, right是开区间

代码

/*
 * @lc app=leetcode.cn id=1094 lang=javascript
 *
 * [1094] 拼车
 */

// @lc code=start
/**
 * @param {number[][]} trips
 * @param {number} capacity
 * @return {boolean}
 */
var carPooling = function (trips, capacity) {
  // 初始 nums 为全为 0
  // 构造差分数组,全为 0
  // diff[i] 为 nums[i] - nums[i-1]
  // 根据题目介绍,0 <= trips[i][1] < trips[i][2] <= 1000,初始数组长度那么也为 1000
  let diff = new Array(1000).fill(0);
  let nums = new Array(1000).fill(0);
  for (let i = 0; i < trips.length; i++) {
    // 上车,对 nums[left](包括nums[left]) 到 nums[right](不包括nums[right])区间的值 + addNumber
    // 下车,对 nums[left](包括nums[left]) 到 nums[right](不包括nums[right])区间的值 - addNumber
    const addNumber = trips[i][0];
    const left = trips[i][1];
    const right = trips[i][2];
    diff[left] += addNumber;
    diff[right] -= addNumber; // 因为不包括 right,所以 right 处也需要减
  }
  nums[0] = diff[0];
  for (let i = 1; i < diff.length; i++) {
    nums[i] = diff[i - 1] + nums[i - 1];
    if (nums[i] > capacity) return false;
  }
  return true;
};
// @lc code=end