差分数组概述
1. 应用场景
频繁对原始数组的某个区间的元素进⾏增减。
给你输⼊⼀个数组 nums,给nums[i…j] 加上 val。
2. 差分数组使用方法
2.1 构造差分数组
对 nums 数组构造⼀个 diff 差分数组,diff[ i ] = nums[ i ] - nums[ i - 1 ]
int[] diff = new int[nums.length];
// 构造差分数组
diff[0] = nums[0];
for (int i = 1; i < nums.length; i++) {
diff[i] = nums[i] - nums[i - 1];
}
2.2 由差分数组反推原始数组
int[] res = new int[diff.length];
// 根据差分数组构造结果数组
res[0] = diff[0];
for (int i = 1; i < diff.length; i++) {
res[i] = res[i - 1] + diff[i];
}
2.3 快速进⾏区间增减的操作
对区间 nums[i…j] 的元素全部加 val
(减 val 就是加 -val)
只需要让 diff [ i ] + = val,diff [ j + i ] - = val
2.4 将差分数组抽象成一个类Difference,包含 increment ⽅法和 result ⽅法:
// 差分数组⼯具类
class Difference {
// 差分数组
private int[] diff;
/* 输⼊⼀个初始数组,区间操作将在这个数组上进⾏ */
public Difference(int[] nums) {
assert nums.length > 0;
/**
* assert <boolean表达式>
* 如果<boolean表达式>为true,则程序继续执行。
* 如果为false,则程序抛出AssertionError,并终止执行
*/
diff = new int[nums.length];
// 根据初始数组构造差分数组
diff[0] = nums[0];
for (int i = 1; i < nums.length; i++) {
diff[i] = nums[i] - nums[i - 1];
}
}
/* 给闭区间 [i,j] 增加 val(可以是负数)*/
public void increment(int i, int j, int val) {
diff[i] += val;
if (j + 1 < diff.length) {
diff[j + 1] -= val;
}
}
/* 返回结果数组 */
public int[] result() {
int[] res = new int[diff.length];
// 根据差分数组构造结果数组
res[0] = diff[0];
for (int i = 1; i < diff.length; i++) {
res[i] = res[i - 1] + diff[i];
}
return res;
}
}
这⾥注意⼀下 increment ⽅法中的 if 语句:
public void increment(int start,int end,int val){
diff[start] += val;
if (end + 1 < diff.length)
diff[end+1] -= val;
}
}
当 j+1 >= diff.length 时,说明是对 nums[i] 及以后的整个数组都进⾏修改,那么就不需要再给 diff 数组减 val 了。
1109. 航班预订统计
这里有 n 个航班,它们分别从 1 到 n 进行编号。
有一份航班预订表 bookings ,表中第 i 条预订记录 bookings[i] = [firsti, lasti, seatsi]
意味着在从 firsti 到 lasti (包含 firsti 和 lasti )的 每个航班 上预订了 seatsi 个座位。
请你返回一个长度为 n 的数组 answer,里面的元素是每个航班预定的座位总数。
示例 1:
输入:bookings = [[1,2,10],[2,3,20],[2,5,25]], n = 5
输出:[10,55,45,25,25]
解释:
航班编号 1 2 3 4 5
预订记录 1 : 10 10
预订记录 2 : 20 20
预订记录 3 : 25 25 25 25
总座位数: 10 55 45 25 25
因此,answer = [10,55,45,25,25]
示例 2:
输入:bookings = [[1,2,10],[2,2,15]], n = 2
输出:[10,25]
解释:
航班编号 1 2
预订记录 1 : 10 10
预订记录 2 : 15
总座位数: 10 25
因此,answer = [10,25]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/corporate-flight-bookings
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution {
public int[] corpFlightBookings(int[][] bookings, int n) {
int r = bookings.length;
int[] diff = new int[n+1]; // 都是从 1 开始存放数字的
int[] res = new int[n+1]; // 有 n 个航班,res[i] 存放第i个航班预订的座位数
for (int i = 0;i < r;i++){
int left = bookings[i][0];
int right = bookings[i][1];
int val = bookings[i][2];
diff[left] += val;
if (right+1 <= n){
diff[right+1] -= val;
}
}
// 由差分数组求原数组 diff[i] = nums[i] - nums[i-1]
res[1] = diff[1];
for (int i = 2;i <= n;i++){
res[i] = diff[i] + res[i-1];
}
return Arrays.copyOfRange(res,1,res.length);
}
}
1094. 拼车
假设你是一位顺风车司机,车上最初有 capacity 个空座位可以用来载客。
由于道路的限制,车 只能 向一个方向行驶(也就是说,不允许掉头或改变方向,你可以将其想象为一个向量)。
这儿有一份乘客行程计划表 trips[][],其中 trips[i] =
[num_passengers, start_location, end_location] 包含了第 i 组乘客的行程信息:
必须接送的乘客数量;
乘客的上车地点;
以及乘客的下车地点。
这些给出的地点位置是从你的 初始 出发位置向前行驶到这些地点所需的距离(它们一定在你的行驶方向上)。
请你根据给出的行程计划表和车子的座位数,来判断你的车是否可以顺利完成接送所有乘客的任务
(当且仅当你可以在所有给定的行程中接送所有乘客时,返回 true,否则请返回 false)。
示例 1:
输入:trips = [[2,1,5],[3,3,7]], capacity = 4
输出:false
示例 2:
输入:trips = [[2,1,5],[3,3,7]], capacity = 5
输出:true
示例 3:
输入:trips = [[2,1,5],[3,5,7]], capacity = 3
输出:true
示例 4:
输入:trips = [[3,2,7],[3,7,9],[8,3,9]], capacity = 11
输出:true
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/car-pooling
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution {
public boolean carPooling(int[][] trips, int capacity) {
int[] res = new int[1010];
// res 是每一站的乘客数量,只要每一站乘客数量都 <= capacity,就返回 true
int[] diff = new int[1010];
// 差分数组
int m = trips.length;
for (int i = 0;i < m;i++){
// 给res数组 从上车地 到 下车地-1 加上乘客数量
// diff[left] += val, diff[right+1] += val
int val = trips[i][0];
int left = trips[i][1];
int right = trips[i][2]-1;
// 第 trips[i][2] 站乘客已经下车,加到 trips[i][2]-1 就可以了
diff[left] += val;
diff[right+1] -= val;
}
// 求出原数组
res[0] = diff[0];
for (int i = 1;i<diff.length;i++){
// diff[i] = nums[i] - nums[i-1]
res[i] = diff[i] + res[i-1];
}
for(int i = 0;i < res.length;i++){
if (res[i] > capacity){
return false;
}
}
return true;
}
}