该问题有两个原因:
-
prev 是一个本地名称,无论在递归调用中 prev 发生什么,它都不会影响调用方的 prev 的值,因为这是一个不同的名称。具体来说,条件if prev is not None永远不会为真; prev 仍然是 None。
- 即使您以某种方式使
prev 成为非本地名称,以便所有递归调用都可以访问相同的prev, these calls (except for the base case), all set previs back toNone. But this is undesired: you should maintain the previous value, except for the case where the top-level (first) call is made: only then should prevbe initialised toNone`。
您可以通过将 prev 定义为全局变量或更好地定义为 self 的属性来解决此问题。这样,递归过程将使用一个prev。
由于您只需要将此 prev 初始化为 None 一次,但有递归调用,因此您应该将初始调用与递归调用分开,并仅在初始调用中执行该初始化。为此,您可以将该函数分成两个函数:主要函数将执行初始化并调用另一个递归函数:
class Solution:
def isValidBSTHelper(self, root: Optional[TreeNode]) -> bool:
if not root:
return True
if not self.isValidBSTHelper(root.left):
return False
if self.prev is not None and self.prev >= root.val:
return False
self.prev = root.val
return self.isValidBSTHelper(root.right)
def isValidBST(self, root: Optional[TreeNode]) -> bool:
self.prev = None # Attribute has larger scope
return self.isValidBSTHelper(root)
您还可以使用具有递归部分的生成器进行中序遍历,然后遍历该迭代器的值并比较它们:
class Solution:
def inorder(self, root: Optional[TreeNode]):
if root:
yield from self.inorder(root.left)
yield root.val
yield from self.inorder(root.right)
def isValidBST(self, root: Optional[TreeNode]) -> bool:
values = self.inorder(root)
prev = next(values, None) # get first value and advance
for val in values:
if prev >= val:
return False
prev = val
return True
或者您可以启动两次中序迭代,一步不同,并在 isValidBST 中使用 zip(inorder 函数保持不变):
def isValidBST(self, root: Optional[TreeNode]) -> bool:
previous = self.inorder(root)
values = self.inorder(root)
next(values, None) # move one iterator one step forward
return all(a < b for a, b in zip(previous, values)) # all pairs must be in order