用线段树来管理日程安排:更高效且更具灵活性
2023-11-30 22:39:24
线段树是一种强大的数据结构,它通过将区间划分为更小的子区间,并对每个子区间存储信息的方式来实现高效的查询和修改操作。这种分治的思想使线段树能够在 O(log n) 的时间复杂度内完成这些操作。
现在,我们开始构建一个基于线段树的 MyCalendar 类。首先,我们定义一个线段树的结点结构:
class Node:
def __init__(self, start, end):
self.start = start
self.end = end
self.left = None
self.right = None
self.booked = False
在这个结构中,每个结点包含了区间的开始和结束时间,以及指向左右子结点的指针。此外,我们还添加了一个 booked
变量,用于标记该区间是否被预订。
接下来,我们定义一些操作来对线段树进行操作:
insert(start, end)
:将一个新的区间插入线段树中。query(start, end)
:查询指定区间内是否有预订。merge(node1, node2)
:将两个线段树结点合并成一个结点。
在实现这些操作之前,我们需要先初始化线段树。我们可以使用以下代码来完成:
def __init__(self):
self.root = None
接下来,我们实现 insert
操作:
def insert(self, start, end):
self.root = self._insert(self.root, start, end)
def _insert(self, node, start, end):
if node is None:
return Node(start, end)
if start <= node.start and end >= node.end:
node.booked = True
return node
if start > node.end or end < node.start:
return node
node.left = self._insert(node.left, start, end)
node.right = self._insert(node.right, start, end)
return node
在 insert
操作中,我们首先检查是否存在一个子区间完全包含要插入的区间。如果存在,则将该子区间的 booked
变量设为 True
,并返回该子区间。如果不存在,则检查要插入的区间是否与子区间相交。如果相交,则将要插入的区间插入到左右子区间中,并更新左右子区间的 booked
变量。
接下来,我们实现 query
操作:
def query(self, start, end):
return self._query(self.root, start, end)
def _query(self, node, start, end):
if node is None:
return False
if start <= node.start and end >= node.end:
return node.booked
if start > node.end or end < node.start:
return False
return self._query(node.left, start, end) or self._query(node.right, start, end)
在 query
操作中,我们首先检查是否存在一个子区间完全包含要查询的区间。如果存在,则返回该子区间的 booked
变量。如果不存在,则检查要查询的区间是否与子区间相交。如果相交,则递归地查询左右子区间,并返回查询结果的逻辑或。
最后,我们实现 merge
操作:
def merge(self, node1, node2):
if node1 is None:
return node2
if node2 is None:
return node1
node1.start = min(node1.start, node2.start)
node1.end = max(node1.end, node2.end)
node1.booked = node1.booked or node2.booked
node1.left = self.merge(node1.left, node2.left)
node1.right = self.merge(node1.right, node2.right)
return node1
在 merge
操作中,我们将两个线段树结点合并成一个结点。首先,我们将两个结点的开始时间和结束时间取最小值和最大值,并将 booked
变量设置为两个结点的 booked
变量的逻辑或。然后,我们将两个结点的左右子结点分别合并,并返回合并后的结点。
这就是基于线段树的 MyCalendar 类的实现。我们可以使用它来高效地管理日程安排。