Design a special dictionary that searches the words in it by a prefix and a suffix.
Implement the WordFilter
class:
WordFilter(string[] words)
Initializes the object with the words
in the dictionary.f(string pref, string suff)
Returns the index of the word in the dictionary, which has the prefix pref
and the suffix suff
. If there is more than one valid index, return the largest of them. If there is no such word in the dictionary, return -1
.For example:
Input
["WordFilter", "f"]
[[["apple"]], ["a", "e"]]
Output
[null, 0]
Explanation
WordFilter wordFilter = new WordFilter(["apple"]);
wordFilter.f("a", "e"); // return 0, because the word at index 0 has prefix = "a" and suffix = "e".
Consider the following constraints:
1 <= words.length <= 10^4
1 <= words[i].length <= 7
1 <= pref.length, suff.length <= 7
words[i]
, pref
and suff
consist of lowercase English letters only.10^4
calls will be made to the function f
.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 goal is to find a word from a given list that matches both a given prefix and a given suffix. The brute force method involves checking every single word in the list to see if it satisfies the given prefix and suffix conditions. It is like comparing the given prefix and suffix against all possibilities one by one until we find a match.
Here's how the algorithm would work step-by-step:
def prefix_suffix_search_brute_force(word_list, prefix, suffix):
matching_word_index = -1
for word_index, word in enumerate(word_list):
# Check if the word starts with the given prefix
if word.startswith(prefix):
# Check if the word ends with the given suffix
if word.endswith(suffix):
# Store the index of the current word
matching_word_index = word_index
return matching_word_index
The trick to solving this problem efficiently is to combine the prefix and suffix into a single, searchable term. This allows us to quickly find words matching both criteria without needing to examine every word individually. We can use a specialized data structure to speed up the search process.
Here's how the algorithm would work step-by-step:
class WordFilter:
def __init__(self, words):
self.prefix_suffix_map = {}
self.separator = '#'
for word_index, word in enumerate(words):
combined_word = word + self.separator + word
for i in range(len(word) + 1):
prefix = combined_word[:i]
for j in range(len(word) + 1):
suffix = combined_word[len(word) + 1 : len(combined_word) - len(word) + j + len(word)]
prefix_suffix = prefix + self.separator + word[len(word) - len(suffix):]
# Store the index of the word for fast retrieval
self.prefix_suffix_map[prefix_suffix] = word_index
def find_index(self, prefix, suffix):
# Construct the combined prefix-suffix key for lookup
combined_search_term = prefix + self.separator + suffix
# Retrieve the index from the map, return -1 if not found
if combined_search_term in self.prefix_suffix_map:
return self.prefix_suffix_map[combined_search_term]
else:
return -1
Case | How to Handle |
---|---|
Empty words array | Return -1, as no word can match an empty dictionary. |
Null words array or null prefix/suffix | Throw IllegalArgumentException to indicate invalid input. |
Words array contains empty strings | Handle empty strings appropriately; the weight of an empty string should be considered. |
Prefix or suffix longer than any word in the words array | No match should be found, return -1. |
Large words array affecting memory usage and search time | Optimize Trie data structure for memory efficiency and use efficient search algorithms. |
Prefix and suffix are the same and match multiple words | Return the largest index of the matching words. |
Prefix and suffix are both empty strings | Return the index of the last word in the words array, representing the highest possible index. |
Integer overflow if word lengths are very large during weight calculation | Use appropriate data types (e.g., long) or modular arithmetic to prevent overflow. |