Волшебный словарь

Нужно создать структуру "волшебный" словарь с методами buildDict и search.
Для метода buildDict будет дан список неповторящихся слов, которые будут использованы для создания словаря.
Для метода search будет дано одно слово, оно может совпадать с каким-то словом из словаря или отличаться от слова в словаре на одну букву.

Пример:

Input: buildDict(["hello", "leetcode"]), Output: Null
Input: search("hello"), Output: False
Input: search("hhllo"), Output: True
Input: search("hell"), Output: False
Input: search("leetcoded"), Output: False

Примечания:

  1. Мы предполагаем, что все слова в словаре написаны маленькими буквами английского алфавита a-z.
  2. Словарь может быть очень большим.
Идея решения
В процессе инициализации словаря мы можем рассортировать слова по "ведрам" (buckets), где каждое ведро содержит слова определенной длины.

Когда поступает слово на поиск, мы берем список слов той же длины, что и искомое слово. И сравниваем слово с каждым кандидатом из списка. Как только встречаем первое несовпадение, заменяем букву. Как только встречаем второе несовпадение, переходим к другому слову из словаря, поскольку по условиям несовпадние может быть одно.

Если не удалось подобрать ни одного слова с 0-1 отличием, то искомое слово в словаре отсутствует.


Имплементаця
class MagicDictionary {
    Map<Integer, ArrayList<String>> buckets; // "ведра"
// хэш-карта, где ключ - длина слова, а значение - список всех слов этой длины. 
 
 public MagicDictionary() {
        buckets = new HashMap();
    } 
 
 
// инициализация 
 public void buildDict(String[] words) {
        for (String word: words) {
            buckets.computeIfAbsent(word.length(), x -> new ArrayList()).add(word);
        }
    } 
 
 // поиск
 public boolean search(String word) {
// если поступило слово длины, которой нет среди ключей хэш-карты, 
// то мы не можем его найти         
        if (!buckets.containsKey(word.length())) return false;
 // в противном случае, мы начинаем его сравнивать со списком из "ведра"
        for (String candidate: buckets.get(word.length())) {
            int mismatch = 0; // считаем количество несовпадений
            for (int i = 0; i < word.length(); ++i) {
                if (word.charAt(i) != candidate.charAt(i)) {
                    if (++mismatch > 1) break; // может быть одно несовпадение
              // в противном случае, мы не можем найти слово 
                }
            }
            if (mismatch <= 1) return true;
        }
        return false;
    }
}

Комментарии

Популярные сообщения из этого блога

Разбиение числа на сумму с максимальным произведнием слагаемых

Число подмассивов, в которых сумма элементов равна k

Сложить два числа, которые представлены списком