966. Vowel Spellchecker
Problem Description
Given a wordlist, we want to implement a spellchecker that converts a query word into a correct word.
For a given query word, the spell checker handles two categories of spelling mistakes:
- Capitalization: If the query matches a word in the wordlist (case-insensitive), then the query word is returned with the same case as the word in the wordlist.
- Vowel Errors: If after replacing the vowels ('a','e','i','o','u') of the query word with any vowel individually, it matches a word in the wordlist (case-insensitive), then the query word is returned with the same case as the match in the wordlist.
In addition, the spell checker operates under the following precedence rules:
- When the query exactly matches a word in the wordlist (case-sensitive), you should return the same word back.
- When the query matches a word up to capitalization, you should return the first such match in the wordlist.
- When the query matches a word up to vowel errors, you should return the first such match in the wordlist.
- If the query has no matches in the wordlist, you should return the empty string.
Example 1:
Input: wordlist = ["KiTe","kite","hare","Hare"], queries = ["kite","Kite","KiTe","Hare","HARE","Hear","hear","keti","keet","keto"]
Output: ["kite","KiTe","KiTe","Hare","hare","","","KiTe","","KiTe"]
Constraints:
1 <= wordlist.length <= 50001 <= queries.length <= 50001 <= wordlist[i].length <= 71 <= queries[i].length <= 7All strings in wordlist and queries consist only of english letters.
Solution
Python Solution
class Solution:
def spellchecker(self, wordlist: List[str], queries: List[str]) -> List[str]:
def devowel(word: str) -> str:
return ''.join('*' if c in 'aeiou' else c.lower() for c in word)
words_perfect = set(wordlist)
words_cap = {}
words_vow = {}
for word in wordlist:
wordlow = word.lower()
words_cap[wordlow] = word
words_vow[devowel(wordlow)] = word
def solve(query: str) -> str:
if query in words_perfect:
return query
queryL = query.lower()
if queryL in words_cap:
return words_cap[queryL]
queryLV = devowel(queryL)
if queryLV in words_vow:
return words_vow[queryLV]
return ""
return [solve(query) for query in queries]
Time Complexity: O(C)
Where C is the total content of wordlist and queries.
Space Complexity: O(C)
We need to store all the words and their variations in our hash maps.
Java Solution
class Solution {
public String[] spellchecker(String[] wordlist, String[] queries) {
Set wordsPerfect = new HashSet<>();
Map wordsCap = new HashMap<>();
Map wordsVow = new HashMap<>();
for (String word : wordlist) {
wordsPerfect.add(word);
String wordlow = word.toLowerCase();
wordsCap.putIfAbsent(wordlow, word);
String wordlowDV = devowel(wordlow);
wordsVow.putIfAbsent(wordlowDV, word);
}
String[] ans = new String[queries.length];
int t = 0;
for (String query : queries) {
ans[t++] = solve(query, wordsPerfect, wordsCap, wordsVow);
}
return ans;
}
private String solve(String query, Set wordsPerfect,
Map wordsCap, Map wordsVow) {
if (wordsPerfect.contains(query)) {
return query;
}
String queryL = query.toLowerCase();
if (wordsCap.containsKey(queryL)) {
return wordsCap.get(queryL);
}
String queryLV = devowel(queryL);
if (wordsVow.containsKey(queryLV)) {
return wordsVow.get(queryLV);
}
return "";
}
private String devowel(String word) {
StringBuilder ans = new StringBuilder();
for (char c : word.toCharArray()) {
ans.append(isVowel(c) ? '*' : c);
}
return ans.toString();
}
private boolean isVowel(char c) {
return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u';
}
}
Time Complexity: O(C)
Where C is the total content of wordlist and queries.
Space Complexity: O(C)
We need to store all the words and their variations in our hash maps.
C++ Solution
class Solution {
public:
vector spellchecker(vector& wordlist, vector& queries) {
unordered_set wordsPerfect;
unordered_map wordsCap;
unordered_map wordsVow;
for (string word : wordlist) {
wordsPerfect.insert(word);
string wordlow = word;
transform(wordlow.begin(), wordlow.end(), wordlow.begin(), ::tolower);
wordsCap[wordlow] = word;
string wordlowDV = devowel(wordlow);
wordsVow[wordlowDV] = word;
}
vector ans;
for (string query : queries) {
ans.push_back(solve(query, wordsPerfect, wordsCap, wordsVow));
}
return ans;
}
private:
string solve(string query, unordered_set& wordsPerfect,
unordered_map& wordsCap,
unordered_map& wordsVow) {
if (wordsPerfect.count(query)) {
return query;
}
string queryL = query;
transform(queryL.begin(), queryL.end(), queryL.begin(), ::tolower);
if (wordsCap.count(queryL)) {
return wordsCap[queryL];
}
string queryLV = devowel(queryL);
if (wordsVow.count(queryLV)) {
return wordsVow[queryLV];
}
return "";
}
string devowel(string word) {
string ans;
for (char c : word) {
ans += isVowel(c) ? '*' : c;
}
return ans;
}
bool isVowel(char c) {
return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u';
}
};
Time Complexity: O(C)
Where C is the total content of wordlist and queries.
Space Complexity: O(C)
We need to store all the words and their variations in our hash maps.
JavaScript Solution
/**
* @param {string[]} wordlist
* @param {string[]} queries
* @return {string[]}
*/
var spellchecker = function(wordlist, queries) {
const wordsPerfect = new Set(wordlist);
const wordsCap = new Map();
const wordsVow = new Map();
for (const word of wordlist) {
const wordlow = word.toLowerCase();
if (!wordsCap.has(wordlow)) {
wordsCap.set(wordlow, word);
}
const wordlowDV = devowel(wordlow);
if (!wordsVow.has(wordlowDV)) {
wordsVow.set(wordlowDV, word);
}
}
function solve(query) {
if (wordsPerfect.has(query)) {
return query;
}
const queryL = query.toLowerCase();
if (wordsCap.has(queryL)) {
return wordsCap.get(queryL);
}
const queryLV = devowel(queryL);
if (wordsVow.has(queryLV)) {
return wordsVow.get(queryLV);
}
return "";
}
function devowel(word) {
return word.replace(/[aeiou]/g, '*');
}
return queries.map(solve);
};
Time Complexity: O(C)
Where C is the total content of wordlist and queries.
Space Complexity: O(C)
We need to store all the words and their variations in our hash maps.
C# Solution
public class Solution {
public string[] Spellchecker(string[] wordlist, string[] queries) {
var wordsPerfect = new HashSet(wordlist);
var wordsCap = new Dictionary();
var wordsVow = new Dictionary();
foreach (string word in wordlist) {
string wordlow = word.ToLower();
if (!wordsCap.ContainsKey(wordlow)) {
wordsCap[wordlow] = word;
}
string wordlowDV = Devowel(wordlow);
if (!wordsVow.ContainsKey(wordlowDV)) {
wordsVow[wordlowDV] = word;
}
}
return queries.Select(query => Solve(query, wordsPerfect, wordsCap, wordsVow)).ToArray();
}
private string Solve(string query, HashSet wordsPerfect,
Dictionary wordsCap,
Dictionary wordsVow) {
if (wordsPerfect.Contains(query)) {
return query;
}
string queryL = query.ToLower();
if (wordsCap.ContainsKey(queryL)) {
return wordsCap[queryL];
}
string queryLV = Devowel(queryL);
if (wordsVow.ContainsKey(queryLV)) {
return wordsVow[queryLV];
}
return "";
}
private string Devowel(string word) {
return new string(word.Select(c => "aeiou".Contains(c) ? '*' : c).ToArray());
}
}
Time Complexity: O(C)
Where C is the total content of wordlist and queries.
Space Complexity: O(C)
We need to store all the words and their variations in our hash maps.