法一:暴力
class Solution {
public int[] corpFlightBookings(int[][] bookings, int n) {
int[] res = new int[n];
for (int i = 0; i < bookings.length; i++) {
int begin = bookings[i][0];
int end = bookings[i][1];
int num = bookings[i][2];
for (int j = begin-1; j < end; j++) {
res[j] += num;
}
}
return res;
}
}
时间复杂度O(bookings.length*j),应该超时的,不知道为什么还过了。
空间复杂度O(n)
法二:差分数组
设a[i]表示第i个航班预订的座位数。
定义一个差分数组tag[],tag[i]表示第i个航班与第i-1个航班预订座位的差,即tag[i] = res[i] - res[i - 1]。
这样每次扫描到[i, j, k],就不需要对区间中的每一个数进行修改操作了,只需要将tag[i]增加k,tag[j + 1]减少k即可,因为区间中的每一个航班都增加相同的座位,它们之间的差并未改变。
本题要求返回每一个航班座位数,所以最后要计算数组res
r
e
s
[
i
]
=
r
e
s
[
i
−
1
]
+
t
a
g
[
i
]
res[i] = res[i - 1] + tag[i]
res[i]=res[i−1]+tag[i]
class Solution {
public int[] corpFlightBookings(int[][] bookings, int n) {
int[] res = new int[n];
int[] tag = new int[n+2];
for (int i = 0; i < bookings.length; i++) {
int begin = bookings[i][0];
int end = bookings[i][1] + 1;
int num = bookings[i][2];
tag[begin] += num;
tag[end] -= num;
}
res[0] = tag[1];
for (int i = 1; i < n; i++) {
res[i] = res[i-1] + tag[i+1]; //下标从0开始,tag+1,不理解打一下表就懂了
}
return res;
}
}
时间复杂度:O(max(n, bookings.length))
空间复杂度:O(n)
法三:树状数组
class Solution {
public int lowbit(int x) {
return x&(-x);
}
public int[] corpFlightBookings(int[][] bookings, int n) {
int[] res = new int[n+1];
for (int[] a : bookings) {
update(a[1],a[2], res);
update(a[0]-1, -a[2], res);
}
for (int i = 1; i <= n; ++i) {
res[i-1] = getSum(i, n, res);
}
int[] newres = new int[n];
for (int i = 0; i < n; i++) {
newres[i] = res[i];
}
return res;
}
// a[1..x] 都加 v
// O(logn)
public void update(int x, int v, int[] res) {
for (int i = x; i > 0; i -= lowbit(i)) {
res[i] += v;
}
}
// O(logn)
int getSum(int x, int n, int[] res) {
int sum = 0;
for (int i = x; i <= n; i += lowbit(i)) {
sum += res[i];
}
return sum;
}
};
时间复杂度:O(nlogn)
就这个题来说,效率不算高,只是一种解题思路。