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

Одна строка является анаграммой другой строки, если в ней используются одинаковые символы в одинаковом количестве. Примером анаграмм могут быть строки “The eyes” и “They see”, потому что они содержат одинаковые символы в одинаковом количестве, хотя они расположены в разном порядке.

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

Давайте начнем с создания пустой функции с именем anagrams(), которая принимает в качестве параметров две строки, stringA и stringB.

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

Чтобы упростить наш код и избежать необходимости создавать две отдельные карты символов в anagrams(), мы создадим вспомогательную функцию. Вспомогательная функция - это функция, которая выполняет часть логики другой функции. Назовем нашу вспомогательную функцию createCharMap(), потому что она предназначена для создания карт наших персонажей.

Как указано в проблеме, нам нужно, чтобы наша строка состояла только из строчных букв и не содержала знаков препинания или пробелов. Для этого мы будем использовать Regex в сочетании с методами JavaScript String .replace() и .toLowerCase().

Регулярное выражение является сокращением от регулярного выражения и представляет собой строку текста, которая создает шаблон для сопоставления, поиска и управления фрагментами текста. каретка или ^ в то время как внутри и в начале скобок или [] означает "not the following”, а метасимвол \w используется для поиска слова символ, который включает любой символ из a-z, A-Z, 0–9, and _.

Метод .replace() возвращает новую строку с шаблоном текста, замененным указанной заменой, а метод .toLowerCase() заменяет каждый символ в строке строчной буквой.

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

str.replace(/[^\w]/g, "").toLowerCase()

Мы можем вставить эту логику «очистки» RegEx, .replace() и .toLowerCase() непосредственно в наш оператор for…of, чтобы убедиться, что мы только повторяем и собираем символы, указанные в инструкциях.

В нашем операторе for…of мы будем использовать обычную технику для сопоставления содержимого строки с объектом. Если символ или char еще не существует в charMap, мы установим его равным 1, но если он уже существует, мы увеличим его значение на +1. После того, как итерация завершится полностью, мы вернем только что заполненное charMap за пределами цикла.

Теперь, когда наша вспомогательная функция настроена, мы можем вызвать ее внутри anagrams(), чтобы создать карту символов для stringA и stringB. Для этого мы объявим в anagrams() две новые переменные с именами aCharMap и bCharMap и установим их равными вспомогательной функции с переданными anagrams() параметрами.

Теперь, когда у нас есть две карты персонажей, мы должны сравнить их содержимое. Однако, прежде чем мы сможем это сделать, мы должны поставить проверку, чтобы избежать крайнего случая. Если два объекта не имеют одинакового количества пар ключ-значение и мы сравниваем только aCharMap с bCharMap, не сравнивая также bCharMap с aCharMap, мы можем получить ложное срабатывание.

Например, если stringA равно hello, а stringB hellos, повторение aCharMap и сравнение его с bCharMap вернет true, потому что код выйдет из цикла, не дойдя до клавиши s в bCharMap. Чтобы избежать необходимости перебирать обе символьные карты для их сравнения, мы можем вместо этого сравнить количество ключей, имеющихся у символьных карт. Если количество ключей отличается, мы сразу узнаем, что две строки не анаграммы.

Чтобы получить количество ключей в каждой карте символов, мы можем использовать Object.keys() метод JavaScript, который возвращает массив всех ключей, присутствующих в объекте. Поскольку Object.keys() возвращает массив, мы можем связать .length с вызовом метода, чтобы получить количество ключей в объекте.

Если две символьные карты имеют одинаковое количество ключей, пора сравнить их содержимое, перебирая одну из карт с помощью оператора for…in . В рамках итерации мы будем return false, если текущий ключ в aCharMap не совпадает с тем же ключом в bCharMap.

Наконец, если две карты символов проходят обе эти проверки, это означает, что строки являются анаграммами друг друга. Все, что осталось сделать, - это return true в конце anagrams(), чтобы достичь результатов.

Решение с помощью .sort ()

Эту проблему также можно решить с помощью метода массива JavaScript .sort(). Метод .sort() может сортировать по алфавиту каждый из элементов в массиве, что избавляет от необходимости создавать или перебирать любые карты символов.

Как и в предыдущем решении, нам нужно будет преобразовать наши строки с помощью Regex, .replace() и .toLowerCase() и поместить эту логику во вспомогательный метод. Однако, поскольку .sort() работает только с массивами, нам нужно преобразовать строку в массив, привязав метод .split() к концу.

После преобразования строки в массив мы создадим новую переменную word и установим для нее значение arr.sort(). Мы хотим, чтобы наша вспомогательная функция возвращала отсортированную по алфавиту строку, а не массив, поэтому мы добавим .join() в конец, чтобы преобразовать word обратно в строку, а затем return word.

Создав нашу sortStr() вспомогательную функцию, мы можем приступить к созданию нашей anagrams() функции. Как и в предыдущем решении, мы вызовем нашу вспомогательную функцию с обоими аргументами, переданными в anagrams(), и сохраним результаты как две новые переменные.

После того, как наши две строки отсортированы, все, что осталось сделать, это сравнить их. Если wordA равно wordB, то две строки являются анаграммами, а наша функция должна return true. Если две переменные не равны, то они не анаграммы, и функция должна return false.

Вывод

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