问题描述
我正在学习二叉搜索树,尝试这个问题二叉树是二叉搜索树还是不是?
通过进行中序遍历,我想检查它是否按升序排列,
def isBst(self,root,prev = None):
if root is not None:
self.isBst(root.left,prev)
if prev != None and root.data <= prev.data:
return False
prev = root
self.isBst(root.right,prev)
else:
return True
在这里,我试图将每个中序遍历存储在 prev 变量中,并使用 prev 检查下一个遍历,如果它小于这意味着它不是 BST ,否则它将返回 True。这就是我想要做的。但在这里我正在尝试这样做,但我不明白我在这里做什么?它不给任何作为输出。
有人可以告诉我并帮助我理解这一点吗?
解决方法
一些问题:
-
函数可以返回
None
,因为if
块没有以return
语句结束,所以会返回默认的None
-
主要问题是您没有使用递归调用的返回值。想象一下,递归调用返回 False,这意味着某处违反了 BST 属性……然后您的代码将忽略该消息并继续处理树的其余部分。所以你至少应该考虑返回值——像这样(但请参阅下一个要点):
valid = self.isBst(root.left,prev) if not valid: return False # ... other code... return True
-
您似乎假设递归调用会修改调用者的
prev
变量的值,但这是不可能的。当您将prev
作为参数传递时,您不会传递 变量,而是传递该变量所具有的值,并且递归执行上下文会创建其自己的prev
变量,该变量以与提供的价值。但是对那个变量的任何赋值都与调用者的prev
变量无关。
与其尝试解决这些问题,我还建议采用一种不同的方法,我发现这种方法也更直观:在单独的函数中创建一个有序迭代器:一个只处理 yielding 一个接一个的值......仅此而已。然后,实际的 isBst
函数可以迭代该迭代器并轻松检测违规。
效果如下:
class Solution:
def traverse(self,root):
if root:
yield from self.traverse(root.left)
yield root.data
yield from self.traverse(root.right)
def isBst(self,root):
inorder = self.traverse(root)
prev = next(inorder,None) # smallest
for value in inorder: # the rest...
if prev > value:
return False
prev = value
return True
使用 itertools.tee
,您可以将 isBst
代码缩短一点:
def isBst(self,root):
import itertools
# get two inorder iterators on the tree's values
iprev,icurr = itertools.tee(self.traverse(root))
# advance one of the two
next(icurr,None)
# check the pairs by consuming both iterators in tandem
return all(prev <= curr for prev,curr in zip(iprev,icurr))