题目描述
这里有n
个航班,它们分别从1
到n
进行编号。
我们这儿有一份航班预订表,表中第i
条预订记录bookings[i] = [i, j, k]
意味着我们在从i
到j
的每个航班上预订了k
个座位。
请你返回一个长度为n
的数组answer
,按航班编号顺序返回每个航班上预订的座位数。
示例:
输入:bookings = [ [1,2,10], [2,3,20], [2,5,25] ], n = 5
输出:[10,55,45,25,25]
O(m*n)解法
根据题意初始化长度为n
的answer
数组,代表1
到n
号航班预订的座位数量,外层遍历 bookings
,内层遍历bookings[i] = [i, j, k]
,计算航班号i
到j
的座位数量,即当前座位数量加k
。
public int[] corpFlightBookings(
int[][] bookings, int n) {
int[] answer = new int[n];
// 遍历整个bookings数组
for (int[] b : bookings) {
// 内层循环把每个航班预订数加上
for (int i = b[0] - 1;
i <= b[1] - 1; i++) {
answer[i] += b[2];
}
}
return answer;
}
O(n)解法
思考
O(m*n)
解法中关键一点,内层循环我们一直重复的在[i, j]
之间加上k
,怎么将这循环变成O(1)
,成为问题的关键!
[i, j]
之间加上k
,这让我想到了等差数列,这不就是公差为k
的等差数列吗?然后呢?
分析
设answer[i]
表示第i
个航班预订的座位数。定义一个差分数组d[]
,d[i]
表示第i
个航班与第i-1
个航班预订座位的差值,即d[i] = answer[i] - answer[i - 1]
。
这样,我们每次遍历到bookings[i] = [i, j, k]
,就只需要将d[i]
增加k
,d[j + 1]
减少k
即可,因为i
到j
之间,航班预订数量是没有变化的。
扫描二维码关注公众号,回复:
10410989 查看本文章
最后,计算answer[i] = answer[i - 1] + d[i]
,返回answer
即可。
推演
好吧,这样说可能有人没懂,我们按照题目的例子推演一次:
- 初始航班预订数量数组
answer = [0,0,0,0,0]
,差分数组d = [0,0,0,0,0]
- 当遍历到
bookings[0] = [1,2,10]
的时候,差分数组第1位加10,第3位减10,变成d = [10,0,-10,0,0]
- 同理,当遍历到
bookings[1] = [2,3,20]
的时候,差分数组变成d = [10,20,-10,-20,0]
- 当遍历到
bookings[2] = [2,5,25]
的时候,差分数组变成d = [10,45,-10,-20,0]
,第6位要减25,我们也不需要了 - 最后计算
answer
数组的值,answer[0] = d[0] = 10
,answer[1] = d[1] + answer[0] = 45 + 10 = 55
,answer[2] = d[2] + answer[1] = -10 + 55 = 45
... - 最最后发现,只申请一个数组表示
d[]
和answer[]
就可以了,over!
代码
public int[] corpFlightBookings(
int[][] bookings, int n) {
int[] answer = new int[n];
// 遍历bookings 计算航班i+1 对航班i 变化的预订数
for (int[] b : bookings) {
// 增加的预订数
answer[b[0] - 1] += b[2];
// 防止数组越界
if (b[1] < n) {
// 减少的预订数量
answer[b[1]] -= b[2];
}
}
// 航班i的预订数等于,i-1的预订数,加i时刻变化的预定数
for (int i = 1; i < n; i++) {
answer[i] += answer[i - 1];
}
return answer;
}