#javascript #recursion
Вопрос:
Может кто-нибудь, пожалуйста, объяснить мне, зачем нам нужен (n-1)
следующий код.
function multiply(arr, n) {
if (n <= 0) {
return 1;
} else {
return multiply(arr, n - 1) * arr[n - 1];
}
}
Я понимаю, что у нас есть базовый if (n <= 0){return 1}
случай, чтобы код не зацикливался вечно, но я не понимаю (n-1)
, как и [n-1]
в рекурсивном случае return multiply(arr, n - 1) * arr[n - 1];
.
Мы очень ценим любую помощь.
Комментарии:
1. Что еще вы там напишете? Вы предполагаете, что прохождение
n
вместоn-1
этого тоже сработает?2. » Я понимаю, что у нас есть заказ на базовый случай, чтобы код не зацикливался навсегда » — ну, вы могли бы объяснить своими словами, как работает это «зацикливание», как бы вы достигли этого базового случая?
Ответ №1:
Похоже, что эта функция предназначена для запуска с последнего элемента массива и рекурсивной работы с каждым более ранним элементом. Вот почему при рекурсивном вызове функции вы должны передать следующий более ранний элемент, т. е. n-1
. Это приближает функцию к базовому варианту с каждой итерацией.
Комментарии:
1. Спасибо за вашу помощь, теперь я это понимаю
2. Это может быть гораздо проще написать с помощью
Array.prototype.reduce()
Ответ №2:
Эта функция просто умножает все элементы данного массива. Первоначально вы должны передать массив, и его длина равна n
.
Последним элементом для любого массива является n-1
. Таким образом, на 1-й итерации он возьмет последний элемент и будет умножаться дальше, пока не достигнет 0. Тогда это прекратится.
Просто попробуйте мысленно запустить эту функцию в своей голове на нескольких простых примерах, и вы ее поймете.
Комментарии:
1. Спасибо за вашу помощь и совет я сделаю так, как вы сказали
Ответ №3:
Функцию можно было бы улучшить, но вы можете понять ее как есть, добавив некоторые журналы отладки…
function multiply(arr, n) {
if (n <= 0) {
return 1;
} else {
console.log(`recurse to multiply ${arr[n-1]} by elements in [${arr.slice(0,n-1)}]`);
return multiply(arr, n - 1) * arr[n - 1];
}
}
multiply([1, 2, 3], 3);
Более четкая реализация не требовала бы параметра длины и была бы более ясной в отношении декомпозиции…
// if the array has a first element, multiply it by the remainder of the array
function multiply(arr) {
return arr.length ? arr[0] * multiply(arr.slice(1)) : 1;
}
console.log(multiply([1,2,3]))
Комментарии:
1. Однако ваша «лучшая реализация» имеет временную сложность
O(n²)
, в отличие от линейной сложности исходной функции.2. Спасибо, @Bergi. Я подумал об этом, но решил, что это более ценно для объяснения рекурсии в общей форме: «обработайте первое и повторите с остальными». Отредактировано, чтобы сказать, что я имел в виду под «лучше».