题目链接:
力扣https://leetcode-cn.com/problems/corporate-flight-bookings/
【分析】这是一道典型的差分数组的应用,何为差分数组呢,下面看一个例子。
下标 i | 0 | 1 | 2 | 3 | 4 |
原始值 arrs | 3 | 5 | 2 | 6 | 9 |
差分 diffs | 3 | 2 | -3 | 4 | 3 |
差分数组的第一个设置为arrs[0],i从1开始,第i个位置为arrs[i] - arrs[i - 1],即当前值和前一个值的差。那么通过差分数组如何还原原始数组呢。首先数组第一个org[0]=diffs[0],后面第i个原始值就是对差分数组求前缀和即可,则org[1] = 3 + 2 = 5, org[2] = 5 - 3 = 2, org[3] = 2 + 4 = 6 ...
如果对原数组进行修改,那么如何体现在差分数组上呢,例如我将下标[1,3]的值+5,那么只需要将diffs[1]+5, diffs[3 + 1] - 5即可,也就是在前端点加,在后端点减。需要特别注意后面数组越界的问题,其实后端点为边界时,无需再将边界外减一个值了,因为我们无需计算边界外数组的值。
class Solution {
public int[] corpFlightBookings(int[][] bookings, int n) {
int[] arrs = new int[n + 1];
int i, m = bookings.length;
for(i = 0; i < m; i++){
arrs[bookings[i][0] - 1] += bookings[i][2];
arrs[bookings[i][1]] -= bookings[i][2];
}
int[] ans = new int[n];
ans[0] = arrs[0];
for(i = 1; i < n; i++){
arrs[i] += arrs[i - 1];
ans[i] = arrs[i];
}
return ans;
}
}
【树状数组】对于这种区间修改,单点查询。我们知道,树状数组也是能做的,只是此时树状数组中维护的是一个差分数组。这道题在初始化的时候tree全部都是0,随着预订,往树状数组中存值。
class Solution {
int[] tree;
int n;
int lowbit(int x){
return x & -x;
}
void add(int x, int val){
for(; x <= n; x += lowbit(x)) tree[x] += val;
}
int ask(int x){
int ans = 0;
for(; x > 0; x -= lowbit(x)) ans += tree[x];
return ans;
}
public int[] corpFlightBookings(int[][] bookings, int n) {
this.n = n;
int[] ans = new int[n];
tree = new int[n + 1];
int m = bookings.length;
int i, j;
for(i = 0; i < m; i++){
add(bookings[i][0], bookings[i][2]);
add(bookings[i][1] + 1, -bookings[i][2]);
}
for(i = 1; i <= n; i++){
ans[i - 1] = ask(i);
}
return ans;
}
}