Javascript: Как рекурсивно вернуть счетчик? - PullRequest
0 голосов
/ 13 апреля 2020

В приведенном ниже примере я не хочу делать счетчик в качестве параметра. Скорее, я просто хочу возвращать «+ 1» каждый раз, чтобы возвращаемое количество шагов. Моя проблема заключается в базовом случае. Если я сделаю return + 1, я получу правильное количество шагов плюс один дополнительный шаг, поэтому я попробовал просто return, но это даст NaN. Возможно ли это вообще?

var numberOfSteps  = function(num) {

    if (num == 0) {
        return;
    } else {
        if (num % 2 == 0) {
            return 1 + numberOfSteps(num/2);
        } else {
            return 1 + numberOfSteps(num - 1);
        }
    }
};

edit : Цель состоит в том, чтобы отследить, сколько шагов нужно, чтобы уменьшить число до 0. Если оно четное, разделить на 2 или вычесть на 1. В конечном итоге я хочу вернуть количество шагов, которое требуется для любого заданного числа, чтобы уменьшить его до 0 в соответствии с этими правилами

Ответы [ 2 ]

3 голосов
/ 13 апреля 2020

Я надеюсь, что в длинной ветке комментариев и других ответах выяснилось, что return + 1 эквивалентно return (+1), то есть возвращает целое число , положительное . А поскольку после достижения нуля не предпринимать никаких шагов, +1 - неправильный ответ. Аналогично, простой return функционально эквивалентен return undefined. Но undefined - это не число, и вы столкнетесь с проблемами, если позже попытаетесь добавить к нему 1. Поэтому решение из комментариев или других ответов возвращает правильное количество шагов, которое в этом случае 0 исправит ваш код.

Я хотел бы указать другой способ решения этой проблемы, хотя:

const numberOfSteps = (n) =>
  n <= 0
    ? 0
    : 1 + numberOfSteps (n % 2 == 0 ? n / 2 : n - 1)

console .log (numberOfSteps (12))

Здесь есть поверхностные отличия от других решений, таких как использование функции стрелки, использование условного выражения (троичного) вместо if -статий и использование <= 0 вместо < 0, чтобы избежать возможных бесконечных циклов на отрицательных числах.

Но принципиальное отличие состоит в том, что этот код имеет только одну рекурсивную ветвь. Я думаю, что это лучшее решение проблемы.

Мы можем думать об этом как о функции, которая отвечает: «Сколько шагов нужно, чтобы достичь 0 из нашего входного числа, если каждый шаг сокращает четные числа в половина и вычитает одно из нечетных? " Хорошо, что логически приводит к базовому случаю (мы уже на 0), поэтому мы должны вернуть 0, и к рекурсивному (мы находимся в некотором натуральном числе), так что нужно добавить 1 к общему количеству шагов Требуется из нашей следующей записи.

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

Если это неясно, тогда эта альтернатива может покажи, что я имею в виду:

const takeStep = (n) =>
  n % 2 == 0 ? n / 2 : n - 1

const numberOfSteps = (n) =>
  n <= 0
    ? 0
    : 1 + numberOfSteps (takeStep (n))
2 голосов
/ 13 апреля 2020

Думаю, вам просто нужно вернуть 0, когда это ... ноль.

var numberOfSteps  = function(num) {

    if (num == 0) {
        return 0;
    } else {
        if (num % 2 == 0) {
            return 1 + numberOfSteps(num/2);
        } else {
            return 1 + numberOfSteps(num - 1);
        }
    }
}

return + 1 возможно, не делает то, что вы думаете: он возвращает число 1. + здесь означает положительное, а не отрицательное, не происходит сложения или вычитания. Это также даст вам слишком много шагов.

return; само по себе возвращает undefined, что при преобразовании в число переводится в NaN, потому что, ну, это не число.

...