ruby - Ruby 中的递归斐波那契数列

标签 ruby recursion fibonacci

这周是我第一次做递归。我能够解决的问题之一是斐波那契数列到第 n 个数字;搞砸了5分钟后并不难。

但是,我无法理解为什么这适用于当前的 return 语句。

return array if num == 2

如果我推送到数组,它不起作用,如果我创建一个新的变量序列并推送到它,它会返回正确的答案。我对此很满意,但我的基本情况是返回数组,而不是序列。我最初将序列插入数组,结果不是 fibs 序列。当我尝试看看如果我插入序列数组会发生什么时,我才解决了这个问题。

我不只是让它工作,我希望有人能够解释幕后发生的事情、堆栈可能是什么以及问题是如何工作的。

我在一定程度上理解递归,并且在某种程度上直观地可以通过假设来使其发挥作用,但我觉得很有趣的是,我实际上不知道其背后的所有原因。

def fib_seq(num)
  return [0] if num == 1
  return [] if num == 0

  array = [0, 1]
  return array if num <= 2 

  seq = fib_seq(num - 1)  
  seq << seq[-2] + seq[-1]
end 

最佳答案

通过删除临时的 array 可以稍微简化代码。多变的。这是一种干扰。它也仅适用于 num == 2 时; num < 2将由其他基本情况处理。 num < 0是非法的,应该通过错误检查来处理。

我还添加了显式返回。显式返回使得返回的内容非常明显,这有助于理解递归。在本例中为 seq 。 (“显式返回是邪恶的!”所有 Ruby 风格的人都哭了。很难受。好的风格不是绝对的。)

def fib_seq(num)
  # Error check
  if num < 0 then
      raise ArgumentError, "The number must be a positive integer"
  end

  # Terminating base cases
  return [] if num == 0
  return [0] if num == 1
  return [0,1] if num == 2 

  # Recursion
  seq = fib_seq(num - 1) 

  # The recursive function
  seq << seq[-2] + seq[-1]

  return seq
end

现在更清楚了 return [0,1] if num == 2是递归的三个基本情况之一。这些是停止递归的终止条件。但处理并没有结束。结果不是[0,1]因为在第一次返回之后堆栈必须展开。

让我们看一下fib_seq(4) .

fib_seq(4) calls fib_seq(3)
fib_seq(3) calls fib_seq(2)
fib_seq(2) returns `[0,1]`

我们已经达到了基本情况,现在我们需要展开调用堆栈。

调用fib_seq(3)从中断处继续。 seqfib_seq(2) 返回是 [0,1] 。它添加了 seq[-2] + seq[-1]到最后并返回 [0,1,1] .

fib_seq(4)从中断处继续。 seqfib_seq(3) 返回是 [0,1,1] 。它添加了 seq[-2] + seq[-1]到最后并返回 [0,1,1,2] .

堆栈已展开,因此我们返回 [0,1,1,2] .

如您所见,实际计算是向后进行的。 f(n) = f(n-1) + f(n-2)f(2) = [0,1] 。它递归到 f(2) ,基本情况,然后展开回做 f(3)使用 f(2) 的结果,和f(4)使用 f(3) 的结果等等。

关于ruby - Ruby 中的递归斐波那契数列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44981517/

相关文章:

vim - 如何在 VIM 中递归使用 Global?

performance - 知道为什么 Go 在递归斐波那契上似乎相对较慢吗?

java - 如何获得斐波那契递归的时间

ruby - 如何在 Ruby Net :HTTP? 中处理多部分 http 响应

ruby-on-rails - 如何根据值从散列中删除重复条目

java - 检查空整数,差不多了

带有索引器的 typescript 递归类型

recursion - 是否有可能在 Lisp 中递归生成 40,000 多个斐波那契数列?

ruby-on-rails - 设计在 authenticate_user 时松开 i18n.locale!开始

ruby - 从本地 .gem 文件安装 'ferret' gem 时,Errno::EEXIST 文件存在错误