This problem requires designing a phone directory data structure that efficiently handles three operations: getting an available phone number, checking if a number is available, and releasing a phone number back to the pool. The optimal approach leverages a HashSet
(or Set
in other languages) to track available phone numbers.
Data Structure:
A HashSet
(or equivalent) is ideal because it provides:
get
, check
, and release
.Algorithm:
__init__
(Constructor): Initializes the HashSet
(available
) with all phone numbers from 0 to maxNumbers - 1
. This represents the initial pool of available numbers.
get()
:
HashSet
is empty. If it is, no numbers are available, so it returns -1.HashSet
(the order doesn't matter). Many languages' Set
implementations offer efficient ways to get an arbitrary element (e.g., using an iterator).HashSet
to indicate it's now assigned.check()
:
number
is present in the HashSet
. Returns true
if it's available (in the set), and false
otherwise.release()
:
number
back to the HashSet
, making it available for future allocation.Time and Space Complexity:
Time Complexity:
get()
: O(1) on average (can be O(n) in the worst case for some implementations of Set, but this is unlikely with a well-designed hash set).check()
: O(1) on average.release()
: O(1) on average.maxNumbers
, to populate the set initially.Space Complexity: O(n), where n is maxNumbers
. This is because the HashSet
stores up to maxNumbers
elements.
Code Examples (with detailed explanations inline):
The code examples provided previously demonstrate the implementation of this algorithm in various programming languages. The key data structure is always a HashSet
(or its equivalent), and the operations directly map to the algorithm steps described above. For instance, in Python, available.pop()
efficiently removes and returns an arbitrary element. In Java, available.iterator().next()
achieves a similar outcome, as does available.begin()
in C++. Each language's set implementation is optimized for efficient average-case performance.