电话目录管理系统

Submission

运行时间: 60 ms

内存: 20.3 MB

class PhoneDirectory:

    def __init__(self, maxNumbers: int):
        self.avail = set(range(maxNumbers))

    def get(self) -> int:
        return self.avail.pop() if self.avail else -1

    def check(self, number: int) -> bool:
        return number in self.avail

    def release(self, number: int) -> None:
        if number not in self.avail:
            self.avail.add(number)


# Your PhoneDirectory object will be instantiated and called as such:
# obj = PhoneDirectory(maxNumbers)
# param_1 = obj.get()
# param_2 = obj.check(number)
# obj.release(number)

Explain

该题解使用两个集合来管理电话号码的分配和释放。`availableNumbers` 集合存储所有当前可用的电话号码,而 `usedNumbers` 集合存储所有已经被分配的电话号码。通过这种方式,我们可以快速检查、分配和释放电话号码。初始化时,所有电话号码都被视为可用。当请求一个电话号码时,从 `availableNumbers` 中移除一个号码并加入到 `usedNumbers` 中。检查电话号码是否可用时,只需查看它是否还在 `availableNumbers` 中。释放电话号码时,从 `usedNumbers` 中移除并重新加入到 `availableNumbers` 中,使其再次可用。

时间复杂度: O(1)

空间复杂度: O(n) 其中 n 是电话目录能容纳的电话号码总数

class PhoneDirectory:

    def __init__(self, maxNumbers: int):
        self.maxNumbers = maxNumbers  # 最大电话号码数量
        self.availableNumbers = set(range(maxNumbers))  # 初始化时,全部电话号码都是可用的
        self.usedNumbers = set()  # 初始时,没有电话号码被使用

    def get(self) -> int:
        if not self.availableNumbers:
            return -1  # 如果没有可用的号码,则返回 -1
        number = self.availableNumbers.pop()  # 从可用号码中获取一个号码
        self.usedNumbers.add(number)  # 将这个号码标记为已使用
        return number

    def check(self, number: int) -> bool:
        return number in self.availableNumbers  # 检查号码是否可用

    def release(self, number: int) -> None:
        if number in self.usedNumbers:
            self.usedNumbers.remove(number)  # 从已使用集合中移除
            self.availableNumbers.add(number)  # 重新加入到可用号码集合中

Explore

在`PhoneDirectory`的设计中,选择使用集合(set)主要基于其在某些操作上具有高效的时间复杂度。特别是,集合的`add`和`remove`操作通常可以在平均O(1)时间内完成,这使得电话号码的分配和释放非常高效。此外,检查一个号码是否存在于集合中的操作也是O(1)时间复杂度,这对于`check`方法尤为重要。相比之下,如果使用列表,检查元素存在性和移除元素通常需要O(n)时间;而使用队列虽然可以快速移除,但检查元素存在性也是O(n)。因此,集合在这种需求下提供了更好的性能。

当`get`方法在集合为空时被调用,它将返回-1,表示没有可用的电话号码。如果连续调用这个方法而集合仍然为空,它将连续返回-1。这种情况下,性能影响主要是由于重复无效调用。每次调用`get`方法时,都需要检查集合是否为空,这是一个O(1)操作。因此,即使在集合为空的情况下频繁调用此方法,性能影响也是可控的,并且对系统资源的消耗较低。

在`release`方法中,如果尝试释放的电话号码已经存在于集合中,实际上并不会发生任何变化,因为集合的性质是不允许重复的元素存在。这种情况下不需要额外的逻辑处理,因为添加一个已存在的元素到集合中是一个无操作(no-op)。`set.add`方法会检查元素是否存在,如果存在则不会进行任何操作。因此,即使在这种情况下调用`release`,也不会对集合的状态或性能产生负面影响。