LC 1109. Corporate Flight Bookings
https://leetcode.com/problems/corporate-flight-bookings/
这题目一上来就是很直白的区间计数,我的第一个想法就是区间树。虽然实现起来很麻烦,但是想试试看看是否work. 因为如果实现正确的话,插入时间复杂度就是O(nlgn), 最后遍历时间复杂度是O(n). 对n<=20000的数据集合应该是没有问题的。
事实证明我实现的区间树是没有问题的,但是就是慢了一点3436ms.
class Tree: def __init__(self, s, e): self.s = s self.e = e self.left = None self.right = None self.val = 0 def build_tree(s, e): if s == e: return Tree(s, e) m = (s + e) // 2 t1 = build_tree(s, m) t2 = build_tree(m + 1, e) t = Tree(s, e) t.left = t1 t.right = t2 return t def update_tree(t, s, e, v): if t.s == s and t.e == e: t.val += v return m = (t.s + t.e) // 2 # [t.s .. m] if t.s <= s <= m: update_tree(t.left, s, min(m, e), v) # [m+1.. t.e] if (m + 1) <= e <= t.e: update_tree(t.right, max(m + 1, s), e, v) return def walk_tree(t, ans, pfx): if t.s == t.e: ans.append(pfx + t.val) return pfx += t.val walk_tree(t.left, ans, pfx) walk_tree(t.right, ans, pfx) return class Solution: def corpFlightBookings(self, bookings: List[List[int]], n: int) -> List[int]: t = build_tree(1, n) for i, j, k in bookings: update_tree(t, i, j, k) ans = [] walk_tree(t, ans, 0) return ans
按照这个时间来看,肯定是还有更好的算法。这个问题就是典型的进出区间的问题,我们可以在
- 在进入某个时间点上+1
- 在出去某个时间点上-1
因为时间点是同质的可累加,所以比如进入时间点t有n次的话,那么就可以在进入t的时候+n.
为了遍历方便,我们可以对时间点做排序。然后在遍历所有的时间点期间,检查对应的进出时间点是否有事件产生。
class Solution: def corpFlightBookings(self, bookings: List[List[int]], n: int) -> List[int]: eva = [(x[0], x[2]) for x in bookings] evb = [(x[1], x[2]) for x in bookings] eva.sort() evb.sort() ans = [] res = 0 pa, pb = 0, 0 for i in range(1, n + 1): while pa < len(eva) and eva[pa][0] == i: res += eva[pa][1] pa += 1 ans.append(res) while pb < len(evb) and evb[pb][0] == i: res -= evb[pb][1] pb += 1 if pb == len(evb): ans.extend([res] * (n - i)) break return ans
接着如果我们的视角从events转移到moments上的话,那么可以设计出更简单的算法。
class Solution: def corpFlightBookings(self, bookings: List[List[int]], n: int) -> List[int]: tmp = [0] * (n + 2) for i, j, k in bookings: tmp[i] += k tmp[j + 1] -= k ans = [] res = 0 for i in range(1, n + 1): res += tmp[i] ans.append(res) return ans