Рекурсия в Js

#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. Я подумал об этом, но решил, что это более ценно для объяснения рекурсии в общей форме: «обработайте первое и повторите с остальными». Отредактировано, чтобы сказать, что я имел в виду под «лучше».