Skip to content

379. Design Phone Directory

On LeetCode ->

Problem

Manage numbers from 0 to maxNumbers - 1, initially all available:

  • get(): allocate any available number, or return -1 if none remain.
  • check(number): report whether the number is available.
  • release(number): make the number available; releasing it twice has no additional effect.
PhoneDirectory(1)
get()       → 0
get()       → -1
check(0)    → False
release(0)  → None
check(0)    → True
get()       → 0
class PhoneDirectory:
    def __init__(self, maxNumbers: int):
        pass

    def get(self) -> int:
        pass

    def check(self, number: int) -> bool:
        pass

    def release(self, number: int) -> None:
        pass

Key trick

Store available numbers in a set: removal allocates, membership checks availability, and insertion releases without duplicates.

Trap

get() may return any available number; tests must not assume ascending order. Repeated releases must not create duplicate allocations.

Why is it interesting?

Choosing the right representation makes every operation simple and eliminates redundant bookkeeping.

Python solution

class PhoneDirectory:
    def __init__(self, maxNumbers: int):
        self.pool = set(range(maxNumbers))

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

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

    def release(self, number: int) -> None:
        # Adding an existing number is harmless.
        self.pool.add(number)

Time: initialization \(O(n)\); operations average/amortized \(O(1)\), where \(n = \text{maxNumbers}\).

Space: \(O(n)\).

Comment on my solution

Your solution is correct under the stated constraints and has the same complexity.

  • available is redundant because the set already tracks availability and supports an emptiness check.
  • Your release guard correctly prevents double-counting, but removing the counter also removes the need for that guard.
  • Add return annotations to get, check, and release.
# WORKS
class PhoneDirectory:
    def __init__(self, maxNumbers: int):
        self.available = maxNumbers
        self.pool = set(range(maxNumbers))

    def get(self):
        if not self.available:
            return -1
        self.available -= 1
        return self.pool.pop()

    def check(self, number: int):
        return number in self.pool

    def release(self, number: int):
        if number not in self.pool:
            self.pool.add(number)
            self.available += 1

Extra

Problem description

Design a phone directory that initially has maxNumbers empty slots that can store numbers. The directory should store numbers, check if a certain slot is empty or not, and empty a given slot.

Implement the PhoneDirectory class:

  • PhoneDirectory(int maxNumbers) Initializes the phone directory with the number of available slots maxNumbers.
  • int get() Provides a number that is not assigned to anyone. Returns -1 if no number is available.
  • bool check(int number) Returns true if the slot number is available and false otherwise.
  • void release(int number) Recycles or releases the slot number.

Example 1:

Input ["PhoneDirectory", "get", "get", "check", "get", "check", "release", "check"] [[3], [], [], [2], [], [2], [2], [2]] Output [null, 0, 1, true, 2, false, null, true]

Explanation PhoneDirectory phoneDirectory = new PhoneDirectory(3); phoneDirectory.get(); // It can return any available phone number. Here we assume it returns 0. phoneDirectory.get(); // Assume it returns 1. phoneDirectory.check(2); // The number 2 is available, so return true. phoneDirectory.get(); // It returns 2, the only number that is left. phoneDirectory.check(2); // The number 2 is no longer available, so return false. phoneDirectory.release(2); // Release number 2 back to the pool. phoneDirectory.check(2); // Number 2 is available again, return true.

Constraints:

  • 1 <= maxNumbers <= 10^4
  • 0 <= number < maxNumbers
  • At most 2 * 10^4 calls will be made to get, check, and release.