«1. Обзор

В этом уроке мы увидим, как проверить, содержит ли строка все буквы алфавита или нет.

Вот краткий пример: «Фермер Джек понял, что большие желтые одеяла дорогие», — что на самом деле содержит все буквы алфавита.

Мы обсудим три подхода.

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

Кроме того, мы обсудим большую сложность используемых подходов.

2. Императивный алгоритм

Реализуем императивный алгоритм. Для этого, во-первых, мы создадим логический массив посещений. Затем мы пройдемся по входной строке символ за символом и пометим символ как посещенный.

Обратите внимание, что прописные и строчные буквы считаются одинаковыми. Таким образом, индекс 0 представляет и A, и a, а индекс 25 представляет и Z, и z.

Наконец, мы проверим, все ли символы в массиве посещений установлены в true:

public class EnglishAlphabetLetters {

    public static boolean checkStringForAllTheLetters(String input) {
        int index = 0;
        boolean[] visited = new boolean[26];

        for (int id = 0; id < input.length(); id++) {
            if ('a' <= input.charAt(id) && input.charAt(id) <= 'z') {
                index = input.charAt(id) - 'a';
            } else if ('A' <= input.charAt(id) && input.charAt(id) <= 'Z') {
                index = input.charAt(id) - 'A';
            }
            visited[index] = true;
        }

        for (int id = 0; id < 26; id++) {
            if (!visited[id]) {
                return false;
            }
        }
        return true;
    }
}

Большая O-сложность этой программы равна O(n), где n — длина строки.

Обратите внимание, что существует множество способов оптимизации алгоритма, например удаление букв из набора и прерывание, как только набор становится пустым. Однако для целей упражнения этот алгоритм достаточно хорош.

3. Использование регулярного выражения

Используя регулярное выражение, мы можем легко получить те же результаты с помощью нескольких строк кода:

public static boolean checkStringForAllLetterUsingRegex(String input) {
    return input.toLowerCase()
      .replaceAll("[^a-z]", "")
      .replaceAll("(.)(?=.*\\1)", "")
      .length() == 26;
}

Здесь мы сначала удаляем из ввода все символы, кроме букв алфавита. . Затем мы удаляем повторяющиеся символы. Наконец, мы подсчитываем буквы и убеждаемся, что у нас есть все из них, 26.

Несмотря на меньшую производительность, Big-O-Complexity этого подхода также стремится к O(n).

4. Java 8 Stream

Используя функции Java 8, мы можем легко добиться того же результата более компактным и декларативным способом, используя фильтр Stream и отдельные методы:

public static boolean checkStringForAllLetterUsingStream(String input) {
    long c = input.toLowerCase().chars()
      .filter(ch -> ch >= 'a' && ch <= 'z')
      .distinct()
      .count();
    return c == 26;
}

Большая-O-сложность этого подход также будет O (n).

4. Тестирование

Давайте проверим счастливый путь для нашего алгоритма:

@Test
public void givenString_whenContainsAllCharacter_thenTrue() {
    String sentence = "Farmer jack realized that big yellow quilts were expensive";
    assertTrue(EnglishAlphabetLetters.checkStringForAllTheLetters(sentence));
}

Здесь предложение содержит все буквы алфавита, следовательно, мы ожидаем, что результат будет истинным.

5. Заключение

В этом уроке мы рассмотрели, как проверить, содержит ли строка все буквы алфавита.

Сначала мы увидели несколько способов реализовать это с помощью традиционного императивного программирования, регулярных выражений и потоков Java 8.

Полный исходный код доступен на GitHub.