使用递归的机制printReverse String

时间:2019-04-18 00:00:42

标签: python algorithm

我正在阅读Explore - LeetCode

它用一个简单但很技巧的例子printReverse

说明了递归
  

让我们从一个简单的编程问题入手:

     
    

以相反的顺序打印字符串。

  
     

您可以轻松地迭代地解决此问题,即从字符串的最后一个字符开始遍历字符串。但是如何递归解决呢?

     

首先,我们可以将所需的函数定义为printReverse(str[0...n-1]),其中str[0]表示字符串中的第一个字符。然后,我们可以分两个步骤完成给定任务:

     
      
  1. printReverse(str[1...n-1]):以相反的顺序打印子字符串str[1...n-1]
  2.   
  3. print(str[0]):打印字符串中的第一个字符。
  4.   
     

请注意,我们在第一步中调用了函数本身,根据定义,这使函数具有递归性。

实施

import unittest
import logging 
logging.basicConfig(level=logging.DEBUG, format="%(levelname)s %(message)s")

def printReverse(s):
    helper(0, s)

def helper(idx, s):
    if s == None or idx >= len(s):
        return 
    logging.debug(f"index:{idx}")
    helper(idx+1, s)
    print(s[idx])

class MyCase(unittest.TestCase):

    def test_printReverse(self):
        s = 'string'
        printReverse(s)

unittest.main()

我对它的工作方式非常困惑。尤其是第一个s [0]不是s而是g。

$ python printReverse.py 
DEBUG index:0
DEBUG index:1
DEBUG index:2
DEBUG index:3
DEBUG index:4
DEBUG index:5
g
n
i
r
t
s
.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK

我承认调用栈正在以

的身份执行
def printReverse2(s):
    stack = []
    for c in s:
        stack.append(c)
    for c in stack:
        print(c)

但是,该过程是隐式的,似乎没有采取这样的步骤将所有字符堆叠在一起,而是立即跳转到for c in stack, print(c)

如何设计调试程序以查看生成调用堆栈的过程?

1 个答案:

答案 0 :(得分:1)

您致电printReverse('string'),后者致电helper(0, 'string')。很好,很清楚。

但是我们如何得到结果呢? print(s[idx])行应打印s-第一个字符,对吗?但是,等等,Python解释器必须先执行上一行helper(idx+1, s)

执行该语句意味着Python必须弹出该执行的结果值(在您的情况下,helper不会返回任何内容,即None),并且实际上每个t, r, i, n, g都有一个新的堆栈框架。看起来如何?

  1. 您用helper(0, 'string')呼叫帮助者
  2. helper(0, 'string')框架在打印helper(1, 'string')的{​​{1}}之前等待'string'[0]'的结果。
  3. s框架等待helper(1, 'string')的结果,然后打印helper(2, 'string')的{​​{1}}
  4. ...
  5. 'string'[1]'等待t的结果
  6. helper(5, 'string')helper(6, 'string')有所不同。 helper(6, 'string')被触发,并且结果为6 >= len('string')-它不必等待任何东西!
  7. 现在if的结果为None,并进行到helper(5, 'string')语句。最后一个字符helper(6, 'string')出现在屏幕上。
  8. print的结果为g,可以继续执行print语句,您将获得helper(4, 'string')
  9. ...等等
  10. ...直到得到helper(5, 'string')的结果,并且原始呼叫n可以打印helper(1, 'string')

您可以使用pdb模块暂停Python程序并逐行执行。