我试图通过使用 javascript 中的 FizzBu​​zz 问题来更好地理解递归

I am trying to better understand recursion by using the FizzBuzz problem in javascript

我不明白第 18 行?如果输入是 100,程序如何在数组中先打印出数字 1 并以数字 100 结束?任何帮助将不胜感激。

function fizzBuzz(n){
  //create empty array called results
  //create base case for when n === 1
  //recurse and push value to array
  var results = [];
  if(n === 1){
    return [1];
  } else {
    if(n % 3 === 0 && n % 5 === 0){
      results.push('FizzBuzz')
    } else if (n % 3 === 0){
      results.push('Fizz')
    } else if (n % 5 === 0){
      results.push('Buzz')
    } else {
      results.push(n);
    }
      return fizzBuzz(n - 1).concat(results); // ???
    }
}

console.log(fizzBuzz(100));

这一行

fizzBuzz(n - 1).concat(results);

可以解释为"append the results we have just gathered for n to the results we generated for f(n - 1)." "Append a to b"表示"put a after b."想想这对n == 2有什么作用,然后一般。

首先要意识到的是,每次调用 fizzBu​​zz returns 一个数组 - 它不会添加到现有数组,每次都会创建一个新数组。

因此,如果输入 n 为 1,它只是 returns 一个包含 1 的单元素数组。

如果n > 1,就会进行递归调用。 "results" 已经创建为一个空数组,因此 .push() 语句将单个元素添加到该数组:

如果 n 可以被 3 和 5 整除,则数组将为 ['FizzBuzz'] 如果 n 只能被 3 整除,则数组将为 ['Fizz'] 如果 n 只能被 5 整除,则数组将为 ['Buzz'] 否则,数组将是 [n],无论 n 是什么。

由于 n > 1(否则我们不会在这里),我们必须使用下一个较低的 n 再次调用 FizzBu​​zz,并将其结果连接到我们的结果。这就是长数组的构建方式 - 通过连接从对 FizzBu​​zz 的递归调用返回的数组。

它首先用最后一个值(对于 100)创建一个 results 数组,然后递归地创建另一个数组,其中包含从 0 到 [=14= 的值的结果],最后以正确的顺序连接它们。

你是对的,这令人困惑。一个更好的递归实现是

function fizzBuzz(n) {
  if (n <= 0) {
    return [];
  }
  var results = fizzBuzz(n - 1);
  if (n % 3 === 0 && n % 5 === 0) {
    results.push('FizzBuzz');
  } else if (n % 3 === 0) {
    results.push('Fizz')
  } else if (n % 5 === 0) {
    results.push('Buzz')
  } else {
    results.push(n);
  }
  return results;
}

console.log(fizzBuzz(100));