
解法:差分数组
前面讲了 前缀和 的方法,利用 前缀和 ,可以得到数组中 num[i] ... nums[j] 任意区间的累加和
而利用 差分数组,可以实现对数据的某个区间段进行频繁的操作,如加减乘除
1、差分数组是啥
题目给的数组 nums
定义一个差分数组 diff
diff[0] = nums[0]
diff[i] = nums[i] - nums[i-1]
差分数组的第 i 项,就是 nums 第 i 项与前一项之差
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
这样就实现了在 left 到 right 的区间内加 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
把 nums 和 diff 的长度都设为 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