Определить, является ли слово палиндромом
Палиндром — это слово, фраза или число, которое читается одинаково слева направо и справа налево. Например, слово "шалаш" или фраза "А роза упала на лапу Азора".
Дана функция: isPalindrom(str), которая аргументом принимает строку - слово и на выходе возвращает булевое значение, обозначающее, является ли слово палиндромом или нет. true- палиндром, false- не палиндром.
Примеры:
isPalindrom("казак") --> true,
isPalindrom("строка") --> false,
isPalindrom("шалаш") --> true,
isPalindrom("Ротор") --> true,
isPalindrom("Письмо") --> false,
Теория
Палиндром — это строка, которая читается одинаково слева направо и справа налево. На практике в задачах по Web-разработке почти всегда требуется дополнительно определить “правила сравнения”: учитывать ли регистр, пробелы, дефисы, букву ё и т.д.
Приведение к единому виду (нормализация входа)
Чтобы пример isPalindrom("Ротор") --> true работал, сравнение должно выполняться без учёта регистра: "Ротор" и "ротор" должны стать одинаковыми. Для этого выполняется преобразование в нижний регистр через toLowerCase().
Иногда требуется Unicode-нормализация: один и тот же видимый символ может быть представлен по-разному (как один кодовый пункт или как последовательность “базовый символ + комбинируемый знак”). Метод normalize() приводит строку к выбранной нормальной форме; практичным вариантом часто является "NFC", так как он приводит к канонической композиции.
normalize("NFC") обычно не влияет на результат, но остаётся безопасной “страховкой” на будущее.Сравнение симметричных позиций
У палиндрома всегда выполняется условие: символ на позиции i равен символу на позиции len - 1 - i.
Из этого следует две полезные идеи:
- достаточно проверить только первую половину строки;
- при первом несовпадении можно сразу вернуть
false(ранний выход), не продолжая вычисления.
Наглядная схема индексов для строки длины 5:
индексы: 0 1 2 3 4
символы: a b c b a
пары: (0,4) (1,3) центр=2
Для чётной длины, например 6:
индексы: 0 1 2 3 4 5
символы: a b c c b a
пары: (0,5) (1,4) (2,3)
Время и память (простыми словами)
Если строка длины n, то в вариантах B и C выполняется примерно n/2 сравнений, но по принятой оценке сложности это O(n), потому что рост линейный. Память в этих вариантах O(1), так как не создаётся строка-«копия наоборот», сравнение происходит “на месте” по индексам.
Вариант A также имеет линейное время, но дополнительно создаёт структуру для разворота (split → массив, затем reverse, затем join), поэтому расход памяти выше.
Разбор крайних случаев
Ниже перечислены ситуации, которые часто встречаются в реальном коде и помогают сделать функцию надёжнее.
- Не строковый ввод: преобразование через
String(str)позволяет избежать ошибок при значениях вроде123,null,undefinedи всегда вернуть булево значение. - Пустая строка и строка из 1 символа: формально являются палиндромами, потому что читаются одинаково в обе стороны; при необходимости можно отдельно ввести правило “длина должна быть больше 1”.
- Пробелы и знаки препинания: в данной формулировке задача про “слово”, поэтому фильтрация не требуется; для “фразового палиндрома” обычно добавляется удаление не-буквенно-цифровых символов и только затем выполняется сравнение.
- Локаль и регистр:
toLocaleLowerCase()может зависеть от локали, поэтому для предсказуемого результата чаще берётсяtoLowerCase().
При необходимости реализации “палиндрома-фразы” может быть добавлен отдельный этап “очистки” строки (пример показан как дополнительный материал):
function isPalindromPhrase(str) {
const s = String(str)
.normalize("NFC")
.toLowerCase()
.replace(/[^0-9a-zа-яё]/gi, "");
let left = 0;
let right = s.length - 1;
while (left < right) {
if (s[left] !== s[right]) return false;
left++;
right--;
}
return true;
}
ё, что делать с дефисом и т.д.; универсального варианта без уточнения правил не существует.Кратко: палиндром определяется сравнением симметричных символов s[i] и s[len - 1 - i], причём достаточно пройти до середины строки. Для примера с "Ротор" требуется приведение к одному регистру, а для большей устойчивости к Unicode-особенностям полезно добавить normalize("NFC"); самым практичным считается подход “два указателя” с O(n) по времени и O(1) по памяти.