Когда вы впервые учитесь программировать, самое важное - добиться от вашего решения желаемых результатов. Можете ли вы взять веревку и перевернуть ее? Можете ли вы найти элемент в массиве? Можете ли вы распечатать список вещей на консоли?
После того, как вы разберетесь с основами, нужно подумать еще о чем: сколько времени требуется для запуска вашего кода. Это важно при увеличении масштабов ваших проектов - в идеале вы хотите как можно быстрее возвращать информацию пользователям вашего приложения.
Нотация Big O - это способ описания времени выполнения кода (ознакомьтесь с этим, чтобы ознакомиться с кратким введением). Давайте сохраним это в уме и определим, является ли строка палиндромом. Начнем с наилучшего сценария:
function isPalindrome(string) { return string[0] === string[string.length-1] }
Здесь вы проверяете только самые первые и самые последние буквы строки. Ваш алгоритм знает, куда идти каждый раз, и его выполнение занимает одинаковое количество времени, независимо от того, сколько букв в строке. Это пример кода, который выполняется во время O (1). Но у нас возникла проблема - что, если первая и последняя буквы совпадают, а следующие за ними - нет? Нам нужно будет просмотреть гораздо больше писем, чем только первое и последнее.
Давайте посмотрим на наше решение для наихудшего сценария:
function isPalindrome(string) { return string === string.split("").reverse().join("") }
Хотя это проще всего записать и аргументировать, на самом деле под капотом происходит много всего:
- Мы разбиваем строку на массив (используя что-то похожее на цикл for)
- Мы меняем этот массив (изменяя индекс каждой буквы в массиве)
- Превращаем преобразованный массив обратно в строку (используя другой цикл for)
Каждый из них требует времени и места для вычисления и увеличивает общее время выполнения.
Давайте посмотрим на наш лучший сценарий:
function isPalindrome(string) { let end = string.length-1 for(let i = 0; i < string.length/2; i++) { if(string[i] !== string[end]) { return false } end-- } return true }
Здесь мы проверяем каждый индекс первой половины строки и сравниваем его с буквой в противоположном индексе. В самом продолжительном сценарии выполнения мы обнаружим, что средние буквы не совпадают после поиска всех других индексов. Это временная сложность O (n). Это означает, что время выполнения потенциально будет таким же длинным, как и ввод.
Давайте рассмотрим еще один случай: определение того, является ли какая-либо подстрока в строке палиндромом. Итак, мы ожидаем, что ввод «hellomomworld» вернет истину, потому что «мама» - это палиндром. Но «желто-красный» вернет false.
function isAnywhere(string){ if(isPalindrome(string)){ return true } for(let i = 0; i < string.length; i++){ for(let j = string.length; j > 3; j--){ if(string.substr(i, j-i).length > 2) { if(isPalindrome(string.substr(i, j-i))){ return true } } } } return false }
Здесь мы берем строку и сначала вызываем функцию isPalindrome, которую мы написали ранее, чтобы проверить, является ли вся строка палиндромом. Если это так, мы можем немедленно вернуть true.
В случае с «адским миром» нам нужно будет погрузиться глубже. Вместо одного цикла for нам теперь нужны два цикла for. Первый цикл будет смотреть на первую букву, затем на следующую и так далее. Второй цикл начинается с последней буквы строки и продолжается в обратном направлении. Мы берем разделы (или подстроки) строки, вставляем их в isPalindrome и продолжаем искать, пока не найдем тот, который является палиндромом. Если их нет, мы вернем false после выхода из циклов. Я также добавил проверку, чтобы убедиться, что подстрока всегда состоит как минимум из 3 букв, потому что одна буква всегда будет равна самой себе.
Наихудший сценарий с этим решением состоит в том, что палиндром находится в конце строки, и наш первый цикл for должен проходить через каждый индекс. На этот раз сложность этого решения составляет O (n²). Если алгоритму требуется O (n) время для запуска одного цикла for, и мы добавляем дополнительный цикл for, который просматривает каждый индекс, это добавит время. Итак, решение с 3 вложенными циклами имеет потенциальную временную сложность O (n³), где n - размер входных данных и т. Д.
Спасибо, что прочитали, и вот несколько дополнительных ресурсов: