前端刷题路-Day98:航班预订统计(题号1109)

512 阅读1分钟

航班预订统计(题号1109)

题目

这里有 n 个航班,它们分别从 1n 进行编号。

有一份航班预订表 bookings ,表中第 i 条预订记录 bookings[i] = [firsti, lasti, seatsi] 意味着在从 firstilasti (包含 firstilasti )的 每个航班 上预订了 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
预订记录 110  10
预订记录 220  20
预订记录 325  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
预订记录 110  10
预订记录 215
总座位数:      10  25
因此,answer = [10,25]

提示:

  • 1 <= n <= 2 * 104
  • 1 <= bookings.length <= 2 * 104
  • bookings[i].length == 3
  • 1 <= firsti <= lasti <= n
  • 1 <= seatsi <= 104

链接

leetcode-cn.com/problems/co…

解释

这题啊,这题是差分数组。

先不说差分数组的概念,正常情况下这题要怎么解?

答案显然很简单,在循环每个区间的时候循环累计数组,给区间内的数组元素添加上需要累积的值即可。

这没啥可说的,正常人都能想到,可这样做是不是有点太耗费性能了?

每次都要遍历区间内的数组,然后进行相加操作,有点费劲,那有什么好的方法么?显然是有的——差分数组。

差分数组是什么?其实是一个固定的概念,别问为什么,这都是前人总结出来的规律。

它的出现就是为了解决区间内批量修改值的操作。

举个🌰:

[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:想查看往期文章和题目可以点击下面的链接:

这里是按照日期分类的👇

前端刷题路-目录(日期分类)

经过有些朋友的提醒,感觉也应该按照题型分类
这里是按照题型分类的👇

前端刷题路-目录(题型分类)