航班预订统计(题号1109)
题目
这里有 n 个航班,它们分别从 1 到 n 进行编号。
有一份航班预订表 bookings ,表中第 i 条预订记录 bookings[i] = [firsti, lasti, seatsi] 意味着在从 firsti 到 lasti (包含 firsti 和 lasti )的 每个航班 上预订了 seatsi 个座位。
请你返回一个长度为 n 的数组 answer,其中 answer[i] 是航班 i 上预订的座位总数。
示例 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]
提示:
1 <= n <= 2 * 1041 <= bookings.length <= 2 * 104bookings[i].length == 31 <= firsti <= lasti <= n1 <= seatsi <= 104
链接
解释
这题啊,这题是差分数组。
先不说差分数组的概念,正常情况下这题要怎么解?
答案显然很简单,在循环每个区间的时候循环累计数组,给区间内的数组元素添加上需要累积的值即可。
这没啥可说的,正常人都能想到,可这样做是不是有点太耗费性能了?
每次都要遍历区间内的数组,然后进行相加操作,有点费劲,那有什么好的方法么?显然是有的——差分数组。
差分数组是什么?其实是一个固定的概念,别问为什么,这都是前人总结出来的规律。
它的出现就是为了解决区间内批量修改值的操作。
举个🌰:
[8, 2, 6, 3, 1]
这是一个很简单的数组,如何从这个数组推导出一个差分数组呢?
利用差分数组的公式:diff[i] = num[i] - num[i - 1]。
当然了,第一个元素不需要处理,从第二个元素开始,代码可以是酱婶的👇:
const num = [8, 2, 6, 3, 1]
const diff = new Array(num.length)
diff[0] = num[0]
for (let i = 1; i < num.length; i++) {
diff[i] = num[i] - num[i - 1]
}
console.log(diff) // [ 8, -6, 4, -3, -2 ]
这样我们就得到了一个差分数组,利用差分数组也可以反推出原数组,代码可以是酱婶的👇:
const origin = new Array(num.length)
origin[0] = diff[0]
for (let i = 1; i < diff.length; i++) {
origin[i] = origin[i - 1] + diff[i]
}
console.log(origin) // [ 8, 2, 6, 3, 1 ]
回到差分数组,在差分数组中可以很方便的进行区间值的加减,比方说需要在数组的[i, j]区间上添加3,只需要进行以下操作:
diff[i] += 3
diff[j + 1] -= 3
这样将差分数组推导回原来数组后,即可拿到累积过后数组了。
在此题中,有着大量的相关操作,使用差分数组后可以将每次操作的时间复杂度降低到O(1),有效减少代码的运行时间。
自己的答案(暴力)
暴力就没啥可说的了,代码简单易懂(除了费时间)👇:
var corpFlightBookings = function(bookings, n) {
const res = new Array(n).fill(0)
for (const booking of bookings) {
for (let i = booking[0] - 1; i < booking[1]; i++) {
res[i] += booking[2]
}
}
return res
};
更好的方法(差分)
利用差分我们可以写出这样的代码👇:
var corpFlightBookings = function(bookings, n) {
const diff = new Array(n + 1).fill(0)
const nums = new Array(n).fill(0)
for (const booking of bookings) {
diff[booking[0]] += booking[2]
if (booking[1] < n) {
diff[booking[1] + 1] -= booking[2]
}
}
nums[0] = diff[1]
for (let i = 2; i <= n; i++) {
nums[i - 1] = nums[i - 2] + diff[i]
}
return nums
};
因为第一个元素的原因,所以差分数组需要更长一截,所以它的长度比nums多一个,在还原的时候也要注意的这个问题,给予适当的i。
其实这里还可以更简化一下,因为原数组都是0,所以可以直接在差分数组的基础上进行修改,不用新建一个数组👇:
var corpFlightBookings1 = function(bookings, n) {
const diff = new Array(n).fill(0)
for (const booking of bookings) {
diff[booking[0] - 1] += booking[2]
if (booking[1] < n) {
diff[booking[1]] -= booking[2]
}
}
for (let i = 1; i < n; i++) {
diff[i] += diff[i - 1]
}
return diff
};
省的折腾就是,不过这种做法需要差分数组的第一个元素就是真正的第一个元素,长度必须为n,所以在遍历bookings的时候需要注意index的变化。
PS:想查看往期文章和题目可以点击下面的链接:
这里是按照日期分类的👇
经过有些朋友的提醒,感觉也应该按照题型分类
这里是按照题型分类的👇