我正在努力解决以下问题:
写入函数,对于给定的二叉树,当树是BST时,返回最小高度的根,而不是BST或NIL。
我知道如何检查树是否是BST但不知道如何重写它。 我很感激伪代码中的算法。
答案 0 :(得分:1)
我没有直接跳到这里有效的算法,而是想提供一系列观察,最终为这个问题找到一个非常好的算法。
首先,假设对于树中的每个节点,您知道以该节点为根的子树中的最大值和最小值的值。 (我们将它们表示为min(x)和max(x),其中x是树中的节点)。鉴于此信息,我们可以进行以下观察:
观察1:如果x≤max(x.left)或x≥min(y.right)
,则节点x是非BST的根
这不是一个if-only-only-if条件 - 它只是一个" if" - 但这是一个有用的观察。这样做的原因是,如果x≤max(x.left),那么x左边的子树中的节点不小于x,这意味着以x为根的树不是' ta BST,如果x> min(x.right),然后x的右子树中的节点不大于x,这意味着以x为根的树不是BST。
现在,不一定是x< min(x.right)和x> max(x.left)是BST的根。考虑这个树,例如:
4
/ \
1 6
/ \
2 5
这里,根节点大于其左子树中的所有内容,并且小于其右子树中的所有内容,但整个树本身不是BST。原因是植根于1和6的树木不是BST。这导致了有用的观察:
观察2:如果x> max(x.left)和x< min(x.right),那么x是一个BST,当且仅当x.left和x.right是BST时。
该结果证明的快速草图:如果x.left和x.right是BST,那么对树的顺序遍历将按升序列出x.left中的所有值,然后是x,然后x.right中的所有值都按升序排列。由于x> max(x.left)和x< min(x.right),这些值被排序,因此树是BST。另一方面,如果x.left或x.right不是BST,那么这些值返回的顺序将不会被排序,因此树不是BST。
这两个属性提供了一种非常好的方法来查找树中不是BST根的每个节点。想法是从树叶向上遍历树中的节点,检查每个节点的值是否大于其左子树的最大值并且小于其右子树的最小值,然后检查其是否为左和正确的子树是BST。您可以使用后序遍历执行此操作,如下所示:
/* Does a postorder traversal of the tree, tagging each node with its
* subtree min, subtree max, and whether the node is the root of a
* BST.
*/
function findNonBSTs(r) {
/* Edge case for an empty tree. */
if (r is null) return;
/* Process children - this is a postorder traversal. This also
* tags each child with information about its min and max values
* and whether it's a BST.
*/
findNonBSTs(r.left);
findNonBSTs(r.right);
/* If either subtree isn't a BST, we're done. */
if ((r.left != null && !r.left.isBST) ||
(r.right != null && !r.right.isBST)) {
r.isBST = false;
return;
}
/* Otherwise, both children are BSTs. Check against the min and
* max values of those subtrees to make sure we're in range.
*/
if ((r.left != null && r.left.max >= r.value) ||
(r.right != null && r.right.min <= r.value)) {
r.isBST = false;
return;
}
/* Otherwise, we're a BST, and our min and max value can be
* computed from the left and right children.
*/
r.isBST = true;
r.min = (r.left != null? r.left.min : r.value);
r.max = (r.right != null? r.right.max : r.value);
}
您已经在树上运行此传递,每个节点都将被标记为是否为二进制搜索树。从那里,您所要做的就是再次通过树,找到最深的节点,而不是BST。我将这作为读者的一个众所周知的练习。 : - )
希望这有帮助!