双重递归调用

时间:2018-12-03 21:16:29

标签: python recursion higher-order-functions

 def print_numbers(n, k):  
 """Print all numbers that (A) can be formed from the digits  of `n` in reverse
order and (B) are multiples of `k`.
  Args:  n (int): The number that results must use digits from. 
 k (int): The number that results must be multiples of.    
  >>> print_numbers(97531, 5) 
     135 
     15
     35"""
   def inner(n,s):
     if n == 0:
        if s % k == 0 and s > 0:
             print(s)
     else:
          inner(n // 10, s*10 + n % 10) #first
          inner(n // 10, s) #second
   inner(n,0)

我在理解递归调用的部分方面有些麻烦。据我了解,第二个递归调用不能在第一个到达阶段之前调用,此时它应该给出返回值。但是,第一个调用的功能(在示例中):  它给出了inner(9753,1),inner(975,13),inner(97,135),inner(9,1357),inner(0,13579)

由于n等于0,因此s(13579)不能被k(5)整除,因此它不会打印任何内容。而且,通过构造函数的返回值为None。因此,当达到inner(0,13579)阶段时,第二个递归调用必须开始工作,但是它将不断尝试0 // 10并且不会继续。

这是我的理解。你能指出我错了吗?

1 个答案:

答案 0 :(得分:1)

夫妇问题。 首先,将递归视为堆栈的层次结构。

  

但是,第一个调用的功能(在示例中):   内部(9753,1),内部(975,13),内部(97,135),内部(9,1357),内部(0,13579)

这里的一个问题是,第一个调用不会被锁定为仅执行该行。每个调用都会在else块中产生两个新的调用。几秒钟后即可获得更多信息。

  

因此,当达到inner(0,13579)阶段时,第二次递归调用   必须开始工作,但是它将不断尝试0 // 10并且不会   继续。

这是有缺陷的。为什么此调用的“ n”值必须为零?如果您还记得的话,则此调用的第一个实例是在else块中,被击中的次数为n = 97531。

它上面的语句进入递归并不重要,因为与该语句的相关堆栈相比,这些变量和值存在于较低的堆栈中。

一种更简单的方法是分别考虑每个堆栈。

stack 1: n = 97531
else: #n//10 = 9753
    child1 (9753,1)
    child2 (9753,0)
            stack2 - child1:
            else: #n//10 = 975
                child11 (975,13)
                child12 (975,1)
            stack2 - child2:
            else: #n//10 = 975
                child21 (975, 3)
                child22 (975, 0) #and so on.

每个层次结构的变量均已确定,并将生成属于较低层次结构的递归函数,直到您分别为每个“分支/生成”命中基本情况为止。

总结 您可以将其简化为堆栈层次结构。那时,此功能变得很容易理解。
本质上,对于数字大于零的每个数字,取出最后一个数字,然后做出两个选择。使用最后一位数字,并丢弃最后一位数字。一遍又一遍地执行此操作,最终您会考虑通过使用或丢弃数字来以相反顺序形成的所有可能数字。