Специфика c Метод суммирования n Число значений массива вместе с рекурсией (алгоритм Javascript) - PullRequest
1 голос
/ 03 мая 2020

Это вопрос

Напишите рекурсивную функцию sum (arr, n), которая возвращает сумму первых n элементов массива arr.

Попытка, которую я нашел на Inte rnet

  function multiply(arr, n) {
    if (n <= 0) {
      return 1;
    } else {
      return multiply(arr, n - 1) + arr[n - 1];
    }
  }

Мой вопрос к вам

1. Как работает оператор else?

Я не могу понять, к чему мы добавляем arr [n - 1].

2. Есть ли более простой способ написания этого кода?

Ответы [ 2 ]

2 голосов
/ 03 мая 2020

Во-первых, эта функция неверна. Я не могу сказать вам, что он пытается сделать, но он определенно не добавляет первые n элементов массива. Итак, как мы подходим к написанию одного? А что такое рекурсия?

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

f(arr, 0) = 0
f(arr, n) = f(n - 1) + arr[n - 1]

Я знаю, что массивы не используются как таковые в математике, но, черт возьми, это все еще полезно посмотреть. Первое, на что следует обратить внимание, это то, что существует два определения, а не одно. Первое определение говорит: сумма первых 0 элементов массива arr всегда равна 0. Независимо от того, что произошло до или после, она всегда будет равна 0.

Второе определение говорит, что для суммирования первых n элементы массива arr, мы должны найти сумму предыдущих элементов, а затем просто добавить arr[n - 1]. Другой способ думать об этом, сумма первых n элементов, это просто сумма первых n - 1 элементов плюс n-й элемент . Это может вызвать головные боли, нет, это вызовет головные боли. Поэтому, чтобы уменьшить вашу боль, мы рассмотрим это шаг за шагом.

Скажем, я передаю функцию f([1, 2, 3, 4], 2), я должен получить 3. Вот как эта функция оценивается в 3:

f([1, 2, 3, 4], 2) = f([1, 2, 3, 4], 1) + [1, 2, 3, 4][1]
f([1, 2, 3, 4], 1) = f([1, 2, 3, 4], 0) + [1, 2, 3, 4][0]
f([1, 2, 3, 4], 0) = 0

И мы закончили. Какая? Были сделаны? Мы уверены, что есть. Обратите внимание, как мы определили каждый вызов функции, который мы сделали? Это означает, что мы можем работать в обратном направлении и заменять каждый вызов функции определением. Итак:

f([1, 2, 3, 4], 0) = 0
f([1, 2, 3, 4], 1) = 0 + 1 = 1
f([1, 2, 3, 4], 2) = 1 + 2 = 3

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

function sum(arr, n)
{
    if (n <= 0) return 0; // f(arr, 0) = 0
    return sum(arr, n - 1) + arr[n - 1]; // f(arr, n) = f(arr, n - 1) + arr[n - 1]
}

Несколько вещей замечать. Вы не можете иметь рекурсию, если функция не возвращает что-то, так как при оценке функция полагается на подстановку. И каждая рекурсивная функция должна иметь как минимум два определения, чтобы l oop мог закончиться. Кроме того, вы видите, как код почти соответствует математическим определениям один к одному? Я знаю, это действительно круто.

Редактировать: if (n == 0) нормально, но не работает, если n отрицательно. Итак, я заменил его на n <= 0.

1 голос
/ 03 мая 2020

Я уже ответил на вопрос в комментариях. Насколько я понимаю, код, который вы разместили, не возвращает правильный результат. Вот как это должно выглядеть:

  function multiply(arr, n) {
    if (n <= 0) { // return 0 if count is 0 or negative
      return 0;
    } else { // sum up the next n - 1 elements with the current element
      return multiply(arr, n - 1) + arr[n - 1];
    }
  }

На самом деле для n=0 результат должен быть 0, а не 1, также при добавлении любого произвольного массива вы получите неверный результат с return 1. Это должно быть return 0. Например, [5,4,3,2] = 14 (старая версия 15).

Поскольку я сейчас отвечаю, я также приложу свой комментарий ниже:

1.) В основном это как работает рекурсия Мы добавляем arr [n - 1] к результату следующего вызова (n-2) и так далее, пока не будет достигнут индекс = 0. Эта рекурсия работает от самого большого до самого низкого элемента индекса в массиве.

2.) Это уже довольно простой способ добиться этого путем рекурсии. Если вы хотите суммировать элементы, вам нужно это утверждение: return multiply(arr, n - 1) + arr[n - 1]; в некоторой форме (рекурсивный вызов + текущий элемент).

Обновление вопроса в комментариях:

var arr = [1,2,3,4], n = 3;

  1. вызов: multiply(arr, n-1) (значение = 0 плюс 1 плюс 2) + arr[n-1] (значение = 3)
  2. вызов: multiply(arr, n-2) (значение = 0 плюс 1) + arr[n-2] (значение = 2)
  3. вызов: multiply(arr, n-3) (значение = 0) + arr[n-3] (значение = 1)
  4. вызов: прекратить из-за 0 (значение = 0)

А теперь подумайте об этом немного по-другому. До окончания рекурсии ничего не подведено. А также в 4. вызове ничего не суммируется, так как мы не ввели ветку else.

Следовательно, первая вычисленная сумма будет:

0 (n-4) + 1 (n-3) .

Будет возвращено следующее вычисление:

(0 (n-4) + 1 (n-3)) + 2 (n-2) .

Последняя рассчитанная сумма также является окончательным результатом:

(0 (n-4) + 1 (n-3) + 2 (n-2)) + 3 (n-1) .

Каждая рекурсия требует двух вещей:

  1. рекурсивный вызов
  2. условие прекратить
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...