Проверьте, содержит ли строка все буквы алфавита

Проверьте, содержит ли строка все буквы алфавита

1. обзор

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

Вот быстрый пример: «Farmer jack realized that big yellow quilts were expensive.», который действительно содержит все буквы алфавита.

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

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

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

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

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

Обратите внимание, чтоUppercase иLowercase считаются одинаковыми. Таким образом, индекс 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 (n), гдеn - длина строки.

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

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

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

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

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

Хотя Big-O-Complexity этого подхода менее производительный, он также имеет тенденцию к O (n).

4. Java 8 Stream

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

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

Big-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));
}

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

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

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

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

Доступен полный исходный кодover on GitHub.