考虑一个简单的情况,例如在BST
中找到第k个最小元素。在我下面的解决方案中:
class Solution:
def kthSmallest(self, root: TreeNode, k: int) -> int:
i = 0
ans = -1
def traverse_inorder(root):
nonlocal i
nonlocal ans
if not root:
return
traverse_inorder(root.left)
i += 1
if i == k:
ans = root.val
return
traverse_inorder(root.right)
traverse_inorder(root)
return ans
我使用nonlocal
作为i
和ans
的良好实践吗?我这样做是为了跟踪到达最左侧节点(最小值)后经过的元素数
另一种解决方案是将i
和ans
作为类的成员变量:
class Solution:
def kthSmallest(self, root: TreeNode, k: int) -> int:
self.i = 0
self.ans = -1
def traverse_inorder(root):
# etc etc
这两种方法是等效的吗?一种做法比另一种好吗?为什么
我认为,在您描述的情况下,您客观地描述的
nonlocal
方法从所示的两个方面更有意义。您希望在函数外有一个计数器,并且无论在递归中的什么位置,都可以在找到结果时跟踪它nonlocal
将该信息完全封装在专用于外部函数特定运行的命名空间中。这里真的没有坏处使用实例属性可以使使用该实例的任何人都可以使用该信息。这在概念上是不必要的,速度稍微慢一些,而且不是线程安全的。虽然线程安全在Python中通常不受关注,但它确实会使代码的健壮性大大降低。在这和封装之间,我绝对不会使用这种方法
我在此建议第三种可能性:使用返回值。在这种情况下,您实际上不需要任何外部名称空间。我不一定推荐使用
nonlocal
,但值得一提。下面是一个示例实现,正如您所看到的,它比您的解决方案要详细得多:有很多方法可以通过返回值实现这一点。这里,我计算每个子树中元素的数量,直到目标值。只有在找到元素的确切数目时,才会返回非none项
相关问题 更多 >
编程相关推荐