【发布时间】:2019-04-16 23:36:06
【问题描述】:
我正在学习 leetcode 的特色教程 Recursion I 中的递归基础知识
第一个练习是反转一个字符串Reverse String - LeetCode
编写一个反转字符串的函数。输入字符串以字符数组的形式给出
char[]。不要为另一个数组分配额外空间,您必须通过使用 O(1) 额外内存就地修改输入数组来做到这一点。
你可以假设所有字符都由printable ascii characters组成。
示例 1:
Input: ["h","e","l","l","o"] Output: ["o","l","l","e","h"]示例 2:
Input: ["H","a","n","n","a","h"] Output: ["h","a","n","n","a","H"]
接受的解决方案是
class Solution:
def reverseString(self, s):
"""
:type s: str
:rtype: str
"""
#base case
if len(s) <= 1:
return s
#recur case
elif len(s) >= 2:
n=len(s)
return self.reverseString(s[n//2:])+self.reverseString(s[:n//2])
解决方案的两个问题:
1、不就地修改
2、递归地对字符串进行切片很昂贵。
作为改进的第一步,引入参数lo和hi来存储索引
class Solution:
def reverseString(self, s, lo=0, hi=None):
"""
:type s: str
:rtype: None
"""
if hi == None:
hi = len(s)
#base case
if hi <= 1:
return s
#recur case
elif hi >= 2:
mid = hi // 2
left = self.reverseString(s, lo, mid)
right = self.reverseString(s, mid, hi)
return left + right
报错
RecursionError: 比较超过最大递归深度
在 0.005 秒内运行 1 次测试
有什么问题?
【问题讨论】:
-
我认为这是你的权利 = self.reverseString(s, mid, hi)。我不明白为什么这个分支会达到基本情况,因为 hi 永远不会改变。
-
根本问题是你没有测试你的代码。您对基本情况的测试与处理
hi的逻辑不匹配。请参阅这个可爱的 debug 博客寻求帮助。 -
将字符串转换为可变类型,然后将其反转并转换回来。一个列表的工作开销约为每个字符 50 个字节。
-
为什么不像我下面那样迭代地做呢?
-
这里的基本思想是有缺陷的。如果您想在没有空间的情况下执行此操作,则需要在某个时候交换元素。但是如果你在中间递归拆分列表,第一个和最后一个元素将永远不会在同一个树分支上。