3491. Phone Number Prefix π
Problem Description
You are given a string array numbers
that represents phone numbers. The task is to determine if no phone number is a prefix of any other phone number in the array. If no such prefix relationship exists, return true
. Otherwise, return false
.
Intuition
The solution to the problem involves sorting and prefix checking. The goal is to ensure that no phone number acts as a prefix for another number within the array. We begin by sorting the numbers
array by the length of the strings, which allows us to compare shorter numbers first with potential candidates.
For each phone number s
in the array, we check all previous entries t
(which are shorter due to sorting) to see if t
is a prefix of s
. If such a prefix t
is found, it means there's a phone number that is a prefix of another, and we return false
. If the loop completes without finding any prefix relations, then we return true
, indicating that no prefix relationships exist.
Solution Approach
The reference solution employs a combination of sorting and prefix checking to solve the problem efficiently. Here's how the solution works:
-
Sorting by Length:
- The array
numbers
is sorted based on the length of the phone numbers. This ensures that when we check prefixes, shorter numbers (which are more likely to be prefixes) are evaluated first.
numbers.sort(key=len)
- The array
-
Iterate and Check Prefixes:
- For each phone number
s
in the sorted array, we examine all preceding numberst
. Since the array is sorted by length, these preceding numbers will all be shorter or equal in length tos
. - For each
s
, we utilize thestartswith
method to see if any preceding numbert
is a prefix ofs
. - If such a prefix relationship is found (
s.startswith(t)
), we returnfalse
immediately, indicating that a prefix conflict exists.
for i, s in enumerate(numbers): if any(s.startswith(t) for t in numbers[:i]): return False
- For each phone number
-
Return Result:
- If the loop completes without identifying any prefixes, return
true
. This signifies that no phone number in the list is a prefix of any other phone number.
return True
- If the loop completes without identifying any prefixes, return
By leveraging sorting and prefix checking within this structured approach, the solution efficiently determines whether any phone number is a prefix of another. The time complexity is mainly influenced by the sorting step, and the prefix checking ensures accuracy within the sorted list.
Ready to land your dream job?
Unlock your dream job with a 2-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's consider a small example to illustrate the solution approach. Suppose we have the following array of phone numbers:
numbers = ["123", "45", "1234", "567"]
Our task is to determine if any phone number in the list is a prefix of another number. Follow these steps:
-
Sorting by Length:
We begin by sorting the array by the length of its contents, so the resulting array becomes:numbers = ["45", "123", "567", "1234"]
This arrangement helps in easily identifying potential prefixes since shorter numbers are more likely to be prefixes.
-
Iterate and Check Prefixes:
- Start iterating through the sorted list. For each number
s
in the list, check all preceding numberst
. Use thestartswith
method to determine if anyt
is a prefix ofs
. - For "45", there are no preceding numbers, so no prefix check is needed.
- For "123", the preceding number is "45", which is not a prefix of "123".
- For "567", the preceding numbers are "45" and "123", neither of which is a prefix of "567".
- Finally, for "1234", check against "45", "123", and "567". Here, "123" is indeed a prefix of "1234".
Detected the prefix situation, so we immediately return
False
. - Start iterating through the sorted list. For each number
-
Return Result: The loop identified a prefix relationship, so the function returns
False
, indicating that a prefix conflict exists in the list.
By using sorting and prefix checking, the method efficiently determines the presence of any prefix relationships among the numbers in the array.
Solution Implementation
1from typing import List
2
3class Solution:
4 def phonePrefix(self, numbers: List[str]) -> bool:
5 # Sort the list of numbers by their length
6 numbers.sort(key=len)
7
8 # Iterate over each number in the sorted list
9 for i, s in enumerate(numbers):
10 # Check if any shorter or equal-length number is a prefix of the current number
11 if any(s.startswith(t) for t in numbers[:i]):
12 # If a prefix match is found, return False
13 return False
14
15 # If no prefix matches were found, return True
16 return True
17
1// Import required packages
2import java.util.Arrays;
3
4class Solution {
5 // Method to check if one phone number is a prefix of any other phone number in the list
6 public boolean phonePrefix(String[] numbers) {
7 // Sort the array of numbers based on the length of each phone number
8 Arrays.sort(numbers, (a, b) -> Integer.compare(a.length(), b.length()));
9
10 // Iterate over each phone number in the sorted array
11 for (int i = 0; i < numbers.length; i++) {
12 String currentNumber = numbers[i];
13
14 // Check if the current number starts with any of the previous numbers
15 for (int j = 0; j < i; j++) {
16 // If current number starts with a previous number, return false
17 if (currentNumber.startsWith(numbers[j])) {
18 return false;
19 }
20 }
21 }
22
23 // If no number is a prefix of another number, return true
24 return true;
25 }
26}
27
1#include <algorithm>
2#include <vector>
3#include <string>
4
5using namespace std;
6
7class Solution {
8public:
9 bool phonePrefix(vector<string>& numbers) {
10 // Sort the numbers based on their length in ascending order
11 sort(numbers.begin(), numbers.end(), [](const string& a, const string& b) {
12 return a.size() < b.size();
13 });
14
15 // Check if any smaller number is a prefix of a larger number
16 for (int i = 0; i < numbers.size(); i++) {
17 // Iterate over all previous numbers
18 for (int j = 0; j < i; j++) {
19 // If the current number starts with any of the previous numbers, return false
20 if (numbers[i].find(numbers[j]) == 0) {
21 return false;
22 }
23 }
24 }
25
26 // Return true if no number is a prefix of another
27 return true;
28 }
29};
30
1// Function to determine if any phone number is a prefix of another in the list
2function phonePrefix(numbers: string[]): boolean {
3 // Sort the array of numbers by their lengths in ascending order
4 numbers.sort((a, b) => a.length - b.length);
5
6 // Iterate over each number in the array
7 for (let i = 0; i < numbers.length; i++) {
8 // Compare current number with all previous numbers
9 for (let j = 0; j < i; j++) {
10 // Check if the current number starts with any of the previous numbers
11 if (numbers[i].startsWith(numbers[j])) {
12 // If a prefix is found, return false
13 return false;
14 }
15 }
16 }
17 // If no prefixes are found, return true
18 return true;
19}
20
Time and Space Complexity
The code sorts the list numbers
based on their lengths. The time complexity for sorting is O(n \times \log n)
, where n
is the number of strings in numbers
.
After sorting, the code iterates over each string s
in numbers
and checks whether any prefix of s
exists among the previous shorter strings. For each string s
, it checks prefixes using s.startswith(t)
for those strings t
. The startswith
operation takes O(m)
time at most, where m
is the length of the string being compared.
Thus, for each string in numbers
, the worst-case number of prefix checks can be O(n)
, leading to O(n \times m)
per string, resulting in a total time complexity for the loop of O(n^2 \times m)
.
Combining the sorting and the loop, the complete time complexity is O(n^2 \times m + n \times \log n)
.
The space complexity primarily considers the sorting operation and storing intermediate results. Sorting takes O(\log n)
space due to the recursive nature of some sorting algorithms.
Storing strings and other operations take additional space, approximately O(m)
, where m
is the average string length. Thus, the space complexity is O(m + \log n)
.
Learn more about how to find time and space complexity quickly.
What is the best way of checking if an element exists in a sorted array once in terms of time complexity? Select the best that applies.
Recommended Readings
Trie Introduction Imagine you have a magic dictionary where as soon as you start spelling a word it immediately tells you how many words that start with those letters How cool would that be This is exactly the kind of magic a data structure called trie performs What's a Trie
Sorting Summary Comparisons We presented quite a few sorting algorithms and it is essential to know the advantages and disadvantages of each one The basic algorithms are easy to visualize and easy to learn for beginner programmers because of their simplicity As such they will suffice if you don't know any advanced
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Want a Structured Path to Master System Design Too? Donβt Miss This!