Write an O(m*n) LeetCode solution of find-and-replace-pattern that beats 100.00% of users with TypeScript [54ms]
![Cover Image for Write an O(m*n) LeetCode solution of find-and-replace-pattern that beats 100.00% of users with TypeScript [54ms]](/_next/image?url=https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1704027081631%2F29b486d8-5aaa-4d78-ae60-3465846364cf.png%3Fw%3D1600%26h%3D840%26fit%3Dcrop%26crop%3Dentropy%26auto%3Dcompress%2Cformat%26format%3Dwebp&w=3840&q=75)
![Cover Image for Write an O(m*n) LeetCode solution of find-and-replace-pattern that beats 100.00% of users with TypeScript [54ms]](/_next/image?url=https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1704027081631%2F29b486d8-5aaa-4d78-ae60-3465846364cf.png%3Fw%3D1600%26h%3D840%26fit%3Dcrop%26crop%3Dentropy%26auto%3Dcompress%2Cformat%26format%3Dwebp&w=3840&q=75)
Try to solve the solution before read this article at: leetcode.com/problems/find-and-replace-pattern
Thoughts:
Transform Words and Pattern:
wordToId that transforms a word into a pattern-like string:wordToId to both the pattern and each word in the words array.Identify Matching Words:
words array.pattern, add the original word to the result array.Return Matching Words:
result array containing the words that match the pattern.words array and m is the length of each word (and the pattern). This is due to iterating through each word and transforming it character by character.wordToId and the transformed strings.graph TD
subgraph "findAndReplacePattern function"
Start("Start") --> Transform["Transform pattern using wordToId"]
Transform --> Iterate["Iterate through words array"]
Iterate --Check if word length matches pattern length--> CheckLength{"Check length"}
CheckLength -- No --> End("End")
CheckLength -- Yes --> Transform2["Transform word using wordToId"]
Transform2 --"Compare transformed word with pattern"--> Compare{"Compare pattern"}
Compare -- No --> Iterate
Compare -- Yes --> AddToResult["Add word to result array"]
AddToResult --> Iterate
End(End)
end
function findAndReplacePattern(words: string[], pattern: string): string[] {
const result: string[] = [];
const wordToId = ((w: string) => {
const idGetter = {
hMap: {} as Record<string, number>,
id: 0,
getId() {
return ++this.id
},
reset() {
this.id = 0
this.hMap = {}
}
}
return [...w].map(c => {
if (idGetter.hMap[c]) {
return idGetter.hMap[c]
} else {
idGetter.hMap[c] = idGetter.getId()
return idGetter.hMap[c]
}
}).join('-')
})
const p = wordToId(pattern)
words.forEach(w => {
if (w.length !== pattern.length) return
const id = wordToId(w)
if (p === id) {
result.push(w)
}
})
return result
};
use std::collections::HashMap;
impl Solution {
pub fn find_and_replace_pattern(words: Vec<String>, pattern: String) -> Vec<String> {
let mut result = Vec::new();
fn hash_word(w: &str) -> String {
let mut char_to_id = HashMap::new();
let mut id = 0;
w.chars().map(|c| {
*char_to_id.entry(c).or_insert_with(|| { id += 1; id })
}).map(|id| id.to_string()).collect::<Vec<_>>().join("-")
}
let p = hash_word(&pattern);
for w in words.iter() {
if w.len() != pattern.len() {
continue;
}
if p == hash_word(w) {
result.push(w.clone());
}
}
result
}
}
func findAndReplacePattern(words []string, pattern string) []string {
result := make([]string, 0)
hashWord := func(w string) string {
hMap := map[rune]int{}
id := 0
hashed := make([]string, 0, len(w))
for _, c := range w {
if _, ok := hMap[c]; !ok {
hMap[c] = id
id++
}
hashed = append(hashed, strconv.Itoa(hMap[c]))
}
return strings.Join(hashed, "-")
}
p := hashWord(pattern)
for _, w := range words {
if len(w) != len(pattern) {
continue
}
if p == hashWord(w) {
result = append(result, w)
}
}
return result
}
LeetCode submissions: TypeScript, Rust, Golang.