给出了二叉树,我们必须计算其中的二叉搜索树的数量。每个叶节点都是BST
我使用了以下方法。
对于bt中的每个节点,检查它是否为bst
上述方法的时间复杂度为O(n 2 )。我们如何以有效的方式O(n)来实现。
答案 0 :(得分:1)
树的简单递归遍历返回一些额外的数据可能有助于在 O(n)时间内管理它,n是节点数。您可以在下面找到Python中的实现。
numBST = 0
def traverse(root):
global numBST
leftComplies = True
rightComplies = True
rootRange = [root.val, root.val]
if root.left != None:
leftResult = traverse(root.left)
leftComplies = leftResult[0] and leftResult[1][1] < root.val
rootRange[0] = leftResult[1][0]
if root.right != None:
rightResult = traverse(root.right)
rightComplies = rightResult[0] and rightResult[1][0] > root.val
rootRange[1] = rightResult[1][1]
if leftComplies and rightComplies:
numBST += 1
return (leftComplies and rightComplies, rootRange)
使用二叉树的根作为参数运行遍历后,numBST将包含根目录中的BST数。
上面给出的函数遍历以递归的方式遍历其树根作为参数。对于每个节点V,如果V具有左子L,则它递归地遍历左子节点并返回一些数据。具体来说,它返回一个长度为2的列表。列表中的第一个元素是一个布尔值,表示以L为根的左子树是否为BST。返回列表的第二个元素包含另一个列表,该列表分别包含以L为根的子树中的最小值和最大值。
对于以V为根的树为BST,以L为根的子树也必须是BST AND 根据L的子树中的最大值(因此该子树中的所有值)必须小于存储在V中的值。因此,在递归调用L的遍历后,我们检查返回的数据以确定是否满足这些条件。
类似地,如果存在V的右子R,则递归遍历。要成为BST,以V为根的树也必须满足以R为根的树是BST AND 以R为根的子树的最小节点(因此该子树中的所有节点)包含的条件一个大于V。
中存储的值的值如果满足所有这些条件,则可以将以V为基础的树视为BST,并相应地更新存储在numBST中的结果。请注意,我们还会更新存储在V中的最小值和最大值,因为我们递归遍历其子L和R,并执行上面提到的检查,以便我们将正确更新的值传递给更高级别的递归。
答案 1 :(得分:1)
如果我正确理解了这个问题,可以解决如下问题;一个将旨在计算作为二进制搜索树的根的节点的数量。正如已经提到的,每个叶子都是二元搜索树的根。非叶节点a
是二进制搜索的根,当且仅当a
的左子节点是二叉搜索树时,b
的右子节点是二元搜索树和a
左子项下所有值的最大值不大于a
的值,并且a
右子项下所有值的最小值更大或等于a
的值。可以通过递归评估来完成对此属性的评估,该评估仅对每个节点进行一次访问,从而产生线性运行时限。