Палиндром с помощью Stream API

5. Палиндром с помощью Stream API

Условие задачи:
Необходимо написать метод, который проверяет, является ли строка палиндромом.

Требования:

  • использовать Stream API;

  • проверку выполнить одним стримом;

  • не учитывать регистр;

  • игнорировать все символы, кроме букв и цифр.

Примеры:

"A man, a plan, a canal: Panama" → true
"I love work in IT"              → false

Спойлеры к решению

Подсказки
💡 Сначала нормализуй строку: убери символы, которые не являются буквами или цифрами, и приведи текст к нижнему регистру.
💡 Достаточно проверить только первую половину строки.
💡 Для каждого индекса i сравни символ с позиции i с симметричным символом length - 1 - i.
💡 Используй IntStream.range() и allMatch().

Решение
public static boolean isPalindrome(String s) {
    String normalized = s
            .replaceAll("[^\\p{L}\\p{N}]", "")
            .toLowerCase(Locale.ROOT);

    return IntStream.range(0, normalized.length() / 2)
            .allMatch(i ->
                    normalized.charAt(i)
                            == normalized.charAt(normalized.length() - 1 - i));
}

Сначала строка нормализуется:

.replaceAll("[^\\p{L}\\p{N}]", "")
.toLowerCase(Locale.ROOT)

\p{L} обозначает любую Unicode-букву, а \p{N} — любую Unicode-цифру. Поэтому решение работает не только с латиницей, но и, например, с кириллицей.

Далее:

IntStream.range(0, normalized.length() / 2)

создаёт индексы только для первой половины строки.

Для каждого индекса сравниваются симметричные символы:

normalized.charAt(i)
        == normalized.charAt(normalized.length() - 1 - i)

allMatch() вернёт true, только если совпали все пары.

Например:

System.out.println(
        isPalindrome("A man, a plan, a canal: Panama")
); // true

System.out.println(
        isPalindrome("I love work in IT")
); // false

Временная сложность — O(n), дополнительная память для нормализованной строки — O(n).