Design a phone directory system that can perform the following operations:
get()
: Provide a number which is not assigned to anyone.check(number)
: Check if a number is available or not.release(number)
: Recycle or release a number.Implement the PhoneDirectory
class:
PhoneDirectory(int maxNumbers)
Initializes the phone directory with the range of numbers [0, maxNumbers - 1]
.int get()
Provides a number which is not assigned to anyone. Returns -1 if no number is available.boolean check(int number)
Returns true
if the number is available and not assigned, and false
otherwise.void release(int number)
Recycles or releases a number.Example 1:
PhoneDirectory directory = new PhoneDirectory(3);
directory.get(); // It can return any available phone number. Here we assume it returns 0.
directory.get(); // It returns 1.
directory.check(2); // Returns true, the number 2 is available.
directory.get(); // It returns 2.
directory.check(2); // Returns false, the number 2 is no longer available.
directory.release(2);
directory.check(2); // Returns true, the number 2 is available again.
Constraints:
1 <= maxNumbers <= 104
0 <= number < maxNumbers
2 * 104
calls will be made to get
, check
, and release
.When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The phone directory problem asks us to manage a pool of phone numbers. The brute force strategy involves simply keeping track of all allocated numbers and, when asked to provide a number, checking every available number to see if it's free.
Here's how the algorithm would work step-by-step:
class PhoneDirectory:
def __init__(self, max_numbers: int):
self.available_numbers = list(range(max_numbers))
self.max_numbers = max_numbers
def get(self) -> int:
# If no numbers left, return -1
if not self.available_numbers:
return -1
phone_number = self.available_numbers.pop(0)
return phone_number
def check(self, phone_number: int) -> bool:
# Checks if the number is available.
return phone_number in self.available_numbers
def release(self, phone_number: int) -> None:
# Only add back numbers in the valid range
if 0 <= phone_number < self.max_numbers:
# Releasing a number makes it available again.
self.available_numbers.append(phone_number)
self.available_numbers.sort()
The phone directory design requires us to efficiently manage and track phone numbers. The optimal approach involves using data structures that allow for quick checks of availability and assignment of numbers. We will maintain a pool of available numbers and efficiently mark numbers as used or available.
Here's how the algorithm would work step-by-step:
class PhoneDirectory:
def __init__(self, max_numbers: int):
self.available_numbers = set(range(max_numbers))
self.max_numbers = max_numbers
def get(self) -> int:
# Check if numbers are available before assigning.
if not self.available_numbers:
return -1
available_number = self.available_numbers.pop()
return available_number
def check(self, number: int) -> bool:
return number in self.available_numbers
def release(self, number: int) -> None:
# Only release numbers within the valid range.
if 0 <= number < self.max_numbers and number not in self.available_numbers:
# Add number back to the available set
self.available_numbers.add(number)
Case | How to Handle |
---|---|
maxNumbers is zero or negative | Throw an IllegalArgumentException or return an error code as no phone numbers can be allocated in this case. |
Calling get() on a number not yet recycled/released | Return -1 to indicate the number is still in use and not available. |
Very large maxNumbers leading to potential integer overflow or memory issues | Consider using long instead of int for storing the number range or choose an appropriate data structure such as a bitset to minimize memory footprint. |
Repeated release of the same phone number. | Ensure the released number is not already in the available set to prevent it being allocated multiple times (could use a set for available numbers). |
Attempting to recycle a number that was never allocated. | Ignore the recycle request or throw an exception to indicate invalid operation. |
Running out of phone numbers after multiple allocations and releases. | Return -1 when get() is called and no available numbers are found. |
Concurrent access to the phone directory from multiple threads. | Use synchronization mechanisms (e.g., locks or atomic operations) to ensure thread safety when accessing and modifying the directory's state. |
maxNumbers is close to Integer.MAX_VALUE | Be aware of potential integer overflow issues when calculating indices or sizes related to the phone directory. |