【问题标题】:I am having trouble understanding this simple recursion problem我无法理解这个简单的递归问题
【发布时间】:2022-01-24 18:51:04
【问题描述】:

这段代码来自“The Bastards Book of Ruby”,它所做的只是找到最大的数字。它作为一个例子来尝试理解递归。 http://ruby.bastardsbook.com/chapters/recursion/

def rock_judger(rocks_arr)    
  if rocks_arr.length <= 2  # the base case
    a = rocks_arr[0]
    b = rocks_arr[-1]
  else
    a = rock_judger(rocks_arr.slice!(0,rocks_arr.length/2))
    b = rock_judger(rocks_arr)
  end    
  return a > b ? a : b
end

为了测试它,我使用数组 [1, 2, 3, 4, 30, 31, 32, 34] 调用了该方法,并使用 pry-byebug gem 调查了到底发生了什么。

第一次运行时,它运行切片!数组上的方法,我们得到[1,2,3,4]。这再次运行,它完成了切片!再次调用方法,返回 [1,2]。然后在这一点上,它分配 a = 1 和 b = 2。

现在我们到了返回方法。 2 > 1,所以它返回 b。但不是只返回整数 2,而是返回到 第 15 行

我的问题是,这怎么可能?这不应该只返回 2 吗?

【问题讨论】:

  • 不要忘记一个方法会将其结果返回到它被调用的地方。
  • 小注:return a &gt; b ? a : b不需要return,因为它是方法中的最后一个表达式,a &gt; b ? a : b和写[a, b].max是一样的
  • @Chris a &gt; b ? a : ba.&lt;=&gt;(b) == 0 时与[a,b].max 不同。相反,它应该是[b,a].maxExample

标签: ruby recursion


【解决方案1】:

在尝试跟踪递归发生的情况时很容易混淆。除了添加“puts”语句之外,使用缩进来隔离不同的递归实例也很有帮助。看看以下是否有帮助。

INDENT = 8
$col = -INDENT
def indent; $col += INDENT; end
def undent; $col -= INDENT; end
def pu(s); puts "#{" "*$col}#{s}"; end 
def puhline; pu('-'*(70-$col)); end
def col; puts "$col=#{$col}"; end
def rock_judger(rocks_arr)    
  indent
  puhline
  pu "rock_judger called with argument #{rocks_arr}"
  pu "rocks_arr.length = #{rocks_arr.length}"
  if rocks_arr.length <= 2  # the base case
    pu "rocks_arr.length <= 2"
    a = rocks_arr[0]
    b = rocks_arr[-1]
    pu "a = #{a}, b = #{b}"
  else
    pu "rocks_arr.length > 2"
    pu "calling rock_judger(#{rocks_arr.dup.slice!(0,rocks_arr.length/2)})"
    a = rock_judger(rocks_arr.slice!(0,rocks_arr.length/2))
    pu "rock_judger returned #{a}"         
    pu "calling rock_judger(#{rocks_arr})"
    b = rock_judger(rocks_arr)
    pu "rock_judger returned #{b}"         
  end 
  c = a > b ? a : b
  pu "a > b ? a : b = #{c}"
  pu "returning #{c}"
  puhline
  undent
  c
end

rocks_arr = [1, 2, 3, 4, 30, 31, 32, 34] 
rock_judger(rocks_arr)
  #=> 34

显示如下。

rock_judger called with argument [1, 2, 3, 4, 30, 31, 32, 34]
rocks_arr.length = 8
rocks_arr.length > 2
calling rock_judger([1, 2, 3, 4])
        rock_judger called with argument [1, 2, 3, 4]
        rocks_arr.length = 4
        rocks_arr.length > 2
        calling rock_judger([1, 2])
                rock_judger called with argument [1, 2]
                rocks_arr.length = 2
                rocks_arr.length <= 2
                a = 1, b = 2
                a > b ? a : b = 2
                returning 2
        rock_judger returned 2
        calling rock_judger([3, 4])
                rock_judger called with argument [3, 4]
                rocks_arr.length = 2
                rocks_arr.length <= 2
                a = 3, b = 4
                a > b ? a : b = 4
                returning 4
        rock_judger returned 4
        a > b ? a : b = 4
        returning 4
rock_judger returned 4
calling rock_judger([30, 31, 32, 34])
        rock_judger called with argument [30, 31, 32, 34]
        rocks_arr.length = 4
        rocks_arr.length > 2
        calling rock_judger([30, 31])
                rock_judger called with argument [30, 31]
                rocks_arr.length = 2
                rocks_arr.length <= 2
                a = 30, b = 31
                a > b ? a : b = 31
                returning 31
        rock_judger returned 31
        calling rock_judger([32, 34])
                rock_judger called with argument [32, 34]
                rocks_arr.length = 2
                rocks_arr.length <= 2
                a = 32, b = 34
                a > b ? a : b = 34
                returning 34
        rock_judger returned 34
        a > b ? a : b = 34
        returning 34
rock_judger returned 34
a > b ? a : b = 34
returning 34

【讨论】:

    猜你喜欢
    • 2020-01-31
    • 2022-12-04
    • 2012-07-07
    • 1970-01-01
    • 2017-07-12
    • 1970-01-01
    • 1970-01-01
    • 2019-09-17
    • 1970-01-01
    相关资源
    最近更新 更多