← Назад к вопросам
Проверка на анаграмму
1.3 Junior🔥 91 комментариев
#Алгоритмы и структуры данных
Условие
Напишите функцию isAnagram(str1, str2), которая проверяет, являются ли две строки анаграммами (содержат одинаковые буквы в одинаковом количестве):
function isAnagram(str1, str2) {
// Ваш код
}
// Примеры:
console.log(isAnagram("listen", "silent")); // true
console.log(isAnagram("hello", "world")); // false
console.log(isAnagram("Dormitory", "dirty room")); // true (игнорируя пробелы и регистр)
Что проверяется
- Работа со строками
- Подсчет символов
- Сравнение объектов или сортировка
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Решение
Анаграмма — это слово или фраза, составленная из букв другого слова/фразы в другом порядке. Разберу несколько подходов.
Подход 1: Сортировка символов
function isAnagram(str1: string, str2: string): boolean {
// Очищаем строки, переводим в нижний регистр
const normalize = (str: string) =>
str.toLowerCase().replace(/[^a-z0-9]/g, "");
const clean1 = normalize(str1);
const clean2 = normalize(str2);
// Сортируем символы и сравниваем
return clean1.split("").sort().join("") === clean2.split("").sort().join("");
}
Как работает:
- Нормализуем обе строки (нижний регистр, удаляем пробелы/знаки)
- Разбиваем на символы
.split("") - Сортируем
.sort() - Объединяем
.join("") - Сравниваем результаты
Временная сложность: O(n log n) из-за сортировки Пространственная сложность: O(n)
Подход 2: Подсчёт символов (оптимально)
function isAnagram(str1: string, str2: string): boolean {
const normalize = (str: string) =>
str.toLowerCase().replace(/[^a-z0-9]/g, "");
const clean1 = normalize(str1);
const clean2 = normalize(str2);
// Если длины разные — не анаграмма
if (clean1.length !== clean2.length) {
return false;
}
// Подсчитываем символы в первой строке
const charCount: Record<string, number> = {};
for (const char of clean1) {
charCount[char] = (charCount[char] || 0) + 1;
}
// Проверяем, что все символы из второй строки есть в первой
for (const char of clean2) {
if (!charCount[char]) {
return false;
}
charCount[char]--;
}
return true;
}
Преимущества:
- Временная сложность: O(n) — линейная
- Пространственная сложность: O(k) где k = количество уникальных символов
- Ранний выход, если длины не совпадают
- Более эффективна на больших строках
Подход 3: С использованием Map
function isAnagram(str1: string, str2: string): boolean {
const normalize = (str: string) =>
str.toLowerCase().replace(/[^a-z0-9]/g, "");
const clean1 = normalize(str1);
const clean2 = normalize(str2);
if (clean1.length !== clean2.length) {
return false;
}
const charMap = new Map<string, number>();
// Подсчитываем символы
for (const char of clean1) {
charMap.set(char, (charMap.get(char) || 0) + 1);
}
// Уменьшаем счётчик
for (const char of clean2) {
if (!charMap.has(char)) {
return false;
}
const count = charMap.get(char)!;
if (count === 1) {
charMap.delete(char);
} else {
charMap.set(char, count - 1);
}
}
return charMap.size === 0;
}
Подход 4: Функциональный с reduce
function isAnagram(str1: string, str2: string): boolean {
const normalize = (str: string) =>
str.toLowerCase().replace(/[^a-z0-9]/g, "");
const clean1 = normalize(str1);
const clean2 = normalize(str2);
if (clean1.length !== clean2.length) {
return false;
}
const countChars = (str: string) =>
[...str].reduce((acc, char) => {
acc[char] = (acc[char] || 0) + 1;
return acc;
}, {} as Record<string, number>);
const count1 = countChars(clean1);
const count2 = countChars(clean2);
return JSON.stringify(count1) === JSON.stringify(count2);
}
Тестирование
console.log(isAnagram("listen", "silent")); // true
console.log(isAnagram("hello", "world")); // false
console.log(isAnagram("Dormitory", "dirty room")); // true
console.log(isAnagram("The Eyes", "They See")); // true
console.log(isAnagram("a", "a")); // true
console.log(isAnagram("ab", "ba")); // true
console.log(isAnagram("", "")); // true
console.log(isAnagram("abc", "def")); // false
console.log(isAnagram("aab", "abb")); // false
Сравнение подходов
| Подход | Время | Память | Читаемость | Когда использовать |
|---|---|---|---|---|
| Сортировка | O(n log n) | O(n) | Простая | Малые строки, интервью для простоты |
| Подсчёт (объект) | O(n) | O(k) | Хорошая | Production, большие данные |
| Map | O(n) | O(k) | Хорошая | TypeScript, когда важна типизация |
| Reduce | O(n) | O(k) | Функциональная | Функциональный стиль |
Рекомендация для интервью
Начните с подхода сортировки (простая и понятная), затем упомяните, что в production используете подход подсчёта символов для лучшей производительности на больших данных.
Ключевые моменты:
- Нормализация важна: нижний регистр, удаление пробелов
- Если длины разные — сразу false
- Подсчёт символов быстрее сортировки на больших объёмах
- Регулярное выражение
[^a-z0-9]удаляет всё кроме букв и цифр