Difficulty: 🟡 Medium
Given a list of strings words
and a string pattern
, return a list of words[i]
that match pattern
. You may return the answer in any order.
A word matches the pattern if there exists a permutation of letters p
so that after replacing every letter x
in the pattern with p(x)
, we get the desired word.
Recall that a permutation of letters is a bijection from letters to letters: every letter maps to another letter, and no two letters map to the same letter.
Example 1:
Input: words = ["abc","deq","mee","aqq","dkd","ccc"], pattern = "abb"
Output: ["mee","aqq"]
Explanation: "mee" matches the pattern because there is a permutation {a -> m, b -> e, ...}.
"ccc" does not match the pattern because {a -> c, b -> c, ...} is not a permutation, since a and b map to the same letter.
Example 2:
Input: words = ["a","b","c"], pattern = "a"
Output: ["a","b","c"]
1 <= pattern.length <= 20
1 <= words.length <= 50
words[i].length == pattern.length
pattern
andwords[i]
are lowercase English letters.
Python3
class Solution:
def findAndReplacePattern(self, words: List[str], pattern: str) -> List[str]:
def is_match(word, pattern):
word_to_pattern = {}
pattern_to_word = {}
for char_word, char_pattern in zip(word, pattern):
if char_word not in word_to_pattern and char_pattern not in pattern_to_word:
word_to_pattern[char_word] = char_pattern
pattern_to_word[char_pattern] = char_word
if (char_word in word_to_pattern and word_to_pattern[char_word] != char_pattern) or \
(char_pattern in pattern_to_word and pattern_to_word[char_pattern] != char_word):
return False
return True
answer = []
for word in words:
if is_match(word, pattern):
answer.append(word)
return answer
The solution involves checking each word in the words
list to determine if it matches the given pattern. To do this, we'll define a helper function, is_match(word, pattern)
, that checks if a given word
matches the pattern
.
Here's how the solution works:
- Define the
is_match(word, pattern)
function that takes a word and a pattern as input. Within this function, initialize two dictionaries,word_to_pattern
andpattern_to_word
, which will store the mapping of characters from the word to the pattern and vice versa. - Iterate through each character pair,
(char_word, char_pattern)
, wherechar_word
is a character from the word andchar_pattern
is a character from the pattern. For each character pair, perform the following steps:- If
char_word
is not in theword_to_pattern
dictionary andchar_pattern
is not in thepattern_to_word
dictionary, this means that the mapping ofchar_word
tochar_pattern
andchar_pattern
tochar_word
has not been established yet. In this case, addchar_word
toword_to_pattern
with a value ofchar_pattern
and addchar_pattern
topattern_to_word
with a value ofchar_word
. - If
char_word
is already in theword_to_pattern
dictionary, check if the value associated withchar_word
is equal tochar_pattern
. If they are not equal, returnFalse
because the mapping is not consistent. - If
char_pattern
is already in thepattern_to_word
dictionary, check if the value associated withchar_pattern
is equal tochar_word
. If they are not equal, returnFalse
because the mapping is not consistent.
- If
- After iterating through all character pairs, if no inconsistencies are found in the mappings, return
True
from theis_match
function, indicating that the word matches the pattern. - In the main part of the solution, initialize an empty list
answer
to store the words that match the pattern. - Iterate through each word in the
words
list. For each word, call theis_match
function with the word and the pattern as arguments. If the function returnsTrue
, append the word to theanswer
list. - After iterating through all words, the
answer
list contains the words that match the pattern. Return theanswer
list as the final result.
- Time Complexity: The solution iterates through the
words
list once and performs checks for each character pair in the word and pattern, leading to a time complexity of O(n * m), where n is the number of words and m is the length of the pattern. - Space Complexity: The solution uses additional space to store the dictionaries
word_to_pattern
andpattern_to_word
, which can have a maximum of 26 lowercase letters as keys and values. Therefore, the space complexity is O(26) ≈ O(1), as it is a constant amount of space.
The provided solution effectively checks each word in the words
list to determine if it matches the given pattern
by establishing mappings between characters. It has a time complexity of O(n * m) and a space complexity of O(1), making it efficient for the given constraints.
Python3
class Solution:
def findAndReplacePattern(self, words: List[str], pattern: str) -> List[str]:
def to_num_array(word):
mapping = {}
return [mapping.setdefault(char, len(mapping)) for char in word]
numeric_pattern = to_num_array(pattern)
answer = []
for word in words:
if numeric_pattern == to_num_array(word):
answer.append(word)
return answer
The solution involves checking each word in the words
list to determine if it matches the given pattern. To do this, we'll define a helper function, to_num_array(word)
, that converts a word into a numeric array based on character mapping. This function will map each character in the word to a unique numeric value, maintaining the order of characters.
Here's how the solution works:
- Define the
to_num_array(word)
function that takes a word as input. Within this function, initialize an empty dictionary calledmapping
. This dictionary will be used to map characters to their corresponding numeric values. Then, iterate through each character,char
, in the word and perform the following steps:- Check if
char
exists as a key in themapping
dictionary. If it does, return the corresponding numeric value usingmapping[char]
. If it does not exist, addchar
as a key to themapping
dictionary with a value equal tolen(mapping)
. This assigns a unique numeric value to each character in the order they appear. - Finally, return a list of numeric values obtained from the mapping for each character in the word. This list represents the numeric array corresponding to the given word.
- Check if
- In the main part of the solution, initialize an empty list
answer
to store the words that match the pattern. - Use the
to_num_array
function to convert the pattern string into a numeric array callednumeric_pattern
. - Iterate through each word in the
words
list. For each word, convert it into a numeric array using theto_num_array
function and store it in a variable callednumeric_word
. - Check if
numeric_pattern
is equal tonumeric_word
. If they are equal, it means the word matches the pattern. In this case, append the original word to theanswer
list. - After iterating through all words, the
answer
list contains the words that match the pattern. Return theanswer
list as the final result.
-
Time Complexity: The solution iterates through each word in the
words
list and converts each word into a numeric array using theto_num_array
function. The conversion takes O(m) time for each word, where m is the length of the word. Therefore, the overall time complexity is O(n * m), where n is the number of words and m is the length of the pattern. -
Space Complexity: The solution uses additional space to store the
mapping
dictionary, which can have at most 26 lowercase letters as keys and values. Therefore, the space complexity is O(26) ≈ O(1), as it is a constant amount of space. Additionally, the numeric arrays have a space complexity of O(m), where m is the length of the pattern. Overall, the space complexity is O(1).
The provided solution effectively checks each word in the words
list to determine if it matches the given pattern
by converting both the pattern and the words into numeric arrays based on character mapping. It has a time complexity of O(n * m) and a space complexity of O(1), making it efficient for the given constraints.
NB: If you want to get community points please suggest solutions in other languages as merge requests.