差分数组介绍和应用
差分数组的主要适用场景是频繁对原始数组的某个区间的元素进行增减
如:输入一个数组 nums
,然后又要求给区间 nums[2..6]
全部加 1,再给 nums[3..9]
全部减 3,再给 nums[0..4]
全部加 2…
如果每次都遍历数组,效率低下,可以考虑构建差分数组
核心代码:
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];
}
diff
差分数组可以反推出原始数组 nums
:
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];
}
这样构造差分数组 diff
,就可以快速进行区间增减的操作,如果你想对区间 nums[i..j]
的元素全部加 3,那么只需要让 diff[i] += 3
,然后再让 diff[j+1] -= 3
即可(注意是j+1)
// 差分数组工具类
class Difference {
private int[] diff;
/* 输入一个初始数组,区间操作将在这个数组上进行 */
public Difference(int[] nums) {
assert nums.length > 0;
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;
}
}
差分数组相关题型
public boolean carPooling(int[][] trips, int capacity) {
// 最大值为1000
int[] diff = new int[1000];
for (int[] trip : trips){
int num = trip[0];
int start = trip[1];
// trip[2]下车,所以上一时刻还有人
int end = trip[2]-1;
diff[start] += num;
if (end+1 < diff.length)
diff[end+1] -= num;
}
int[] res = new int[diff.length];
res[0] = diff[0];
for (int i = 1; i < res.length; i++) {
res[i] = diff[i] + res[i-1];
}
for (int i = 0; i < res.length; i++) {
if (capacity<res[i])
return false;
}
return true;
}
public int[] corpFlightBookings(int[][] bookings, int n) {
int[] answer = new int[n];
int[] diff = new int[n];
for (int[] booking : bookings){
// 因为n从1开始编号,所以下边统减一
int first = booking[0]-1;
int last = booking[1]-1;
int seat = booking[2];
diff[first] += seat;
if(last + 1 < n)
diff[last+1] -= seat;
}
answer[0] = diff[0];
for (int i = 1; i < n; i++) {
answer[i] = diff[i] + answer[i-1];
}
return answer;
}