【问题标题】:Explanation of Recursion with Fibonacci Numbers用斐波那契数解释递归
【发布时间】:2014-01-16 15:54:57
【问题描述】:

我找到了一个代码,它可以确定一个数字是否是斐波那契数。我希望有人能够更容易地分解它。

def is_fibonacci?(i, current = 1, before = 0)  
  return true if current == i || i == 0
  return false if current > i
  is_fibonacci?(i, current + before, current)
end

is_fibonacci?(3) # => true
is_fibonacci?(4) # => false

我知道一个方法在递归中调用自己,并且需要有一个基本情况,但是我再次很难想象正在发生的事情。任何帮助将不胜感激。

【问题讨论】:

  • 感谢大家的帮助!每个解释都有帮助,现在终于有意义了!再次感谢
  • 那么你应该接受一个答案,并为所有其他有用的答案投票。
  • @user3007294 答案有帮助吗?

标签: ruby algorithm recursion fibonacci


【解决方案1】:

如果is_fibonacci? 有两个值10144,您可以检查调用跟踪。它显然是在计算小于或等于给定值的斐波那契数,然后在递归中进行比较。

  is_fibonacci?(10, current = 1, before = 0)
   is_fibonacci?(10, current = 1, before = 1)
    is_fibonacci?(10, current = 2, before = 1)
     is_fibonacci?(10, current = 3, before = 2)
      is_fibonacci?(10, current = 5, before = 3)
       is_fibonacci?(10, current = 8, before = 5)
        is_fibonacci?(10, current = 13, before = 8)
  is_fibonacci?(144, current = 1, before = 0)
   is_fibonacci?(144, current = 1, before = 1)
    is_fibonacci?(144, current = 2, before = 1)
     is_fibonacci?(144, current = 3, before = 2)
      is_fibonacci?(144, current = 5, before = 3)
       is_fibonacci?(144, current = 8, before = 5)
        is_fibonacci?(144, current = 13, before = 8)
         is_fibonacci?(144, current = 21, before = 13)
          is_fibonacci?(144, current = 34, before = 21)
           is_fibonacci?(144, current = 55, before = 34)
            is_fibonacci?(144, current = 89, before = 55)
             is_fibonacci?(144, current = 144, before = 89)
10 : false ,  144 : true

这是为前 10 个斐波那契数提供此输出的代码:

def fib(n)
  if n <= 0 then 1
  else
    fib(n-1) + fib(n - 2)
  end
end


def is_fibonacci?(i, current = 1, before = 0, level=0)  
  puts (" " * level) + "  is_fibonacci?(#{i}, current = #{current}, before = #{before})"
  if current == i || i == 0 then
    return true 
  elsif current > i then
    return false 
  else
    is_fibonacci?(i, current + before, current, level+1)
  end
end

(0..10).each do |i|
  n = fib(i)
  ifib =is_fibonacci?(i)
  nfib = is_fibonacci?(n)
  puts "#{i} : #{ifib} ,  #{n} : #{nfib}"
end

【讨论】:

    【解决方案2】:

    基本上,它是一个接受3 参数的函数。

    i - 您正在测试的数字是否是序列的一部分。

    current - 您正在测试的当前斐波那契数,默认为 1,因此您不需要提供第二个参数。

    before - 序列中current 之前的斐波那契数,默认为0,因此您不需要提供第三个参数。

    示例值

    如果current5,则before3

    如果current8,则before5

    该函数比较第一个参数i 的值,并查看它是否等于0current 斐波那契值。如果等于current0,则为斐波那契数(因为0是序列中的第一个数)。

    然后查看current 是否大于i。如果较大,则不在序列中。这是因为如果5current 值,则继续检查4 是否在序列中是没有意义的。

    如果这两种情况都不匹配,我们只需再次调用该函数,传入i的值,找到序列current + before中的下一个数字,before的值将是current序号。

    示例:

    i15current5before3。再次调用该函数时,会调用

    is_fibonacci?(i, current + before, current)
    

    这将评估为

    is_fibonacci?(15, 5 + 3, 5
    

    注意

    Ruby 有一个很好的语法,if 可以出现在你想要发生的事情之后

    if a < b
        puts "#{a} is greater than #{b}"
    

    完全一样

    puts "#{a} is greater than #{b}" if a < b
    

    它只是减少了行数,并且读起来更像英语。

    【讨论】:

      【解决方案3】:

      可视化它的最简单方法是一次通过计算一个方法调用,假设我们想要评估is_fibonacci?(8),那么 ruby​​ 将设置current = 1, before = 0,因为我没有覆盖默认值。

      那么,由于i既不是0也不是8,所以要递归,所以会发生下面的方法调用:

      is_fibonacci?(8, 1, 1)
      is_fibonacci?(8, 2, 1)
      is_fibonacci?(8, 3, 2)
      is_fibonacci?(8, 5, 3)
      is_fibonacci?(8, 8, 5)
      

      最后,is_fibonacci?(8, 8, 5) 可以从i == current (8 == 8) 终止,所以它返回 true。

      编辑:考虑这种递归的另一种方法是,您的 currentbefore 参数正在“重建”斐波那契数列,如果它们达到 i,那么答案是正确的,但如果它们超过 @ 987654330@,是假的。

      【讨论】:

        【解决方案4】:
        1. 首先它检查i(请求的数字)是否等于传递给current变量的Fibonaccy计算的数字,或者为零。如果相等则返回true:

          return true if current == i || i == 0
          
        2. 其次,它检查i 是否低于current 变量。如果是,i var 永远不会成为斐波那契数,所以返回 false

          return false if current > i
          
        3. 至少我们调用来计算下一个斐波那契数,将下一个数字作为当前和先前数字的总和传递给第二个参数,并将当前数字作为下一步的第三个参数。

          is_fibonacci?(i, current + before, current)
          

        请注意,最好的方法是将尾递归(如您的示例中所示)扩展为循环。

        【讨论】:

          猜你喜欢
          • 2016-06-27
          • 2014-09-25
          • 2010-12-03
          • 2011-07-27
          • 1970-01-01
          • 1970-01-01
          • 2014-04-02
          • 2018-03-02
          相关资源
          最近更新 更多