找到不是 BST 的最小高度的根
Find root of minimal height which is not BST
我正在努力解决以下问题:
编写函数,对于给定的二叉树 returns 当树是 BST 时,最小高度的根不是 BST 或 NIL。
我知道如何检查树是否是 BST 但不知道如何重写它。
如果有伪代码算法,我将不胜感激。
我不想直接跳到此处适用的算法,而是给出一系列观察结果,最终得出一个非常好的算法来解决这个问题。
首先,假设对于树中的每个节点,您知道以该节点为根的子树中的最大值和最小值。 (我们将它们表示为 min(x) 和 max(x),其中 x 是树中的一个节点)。鉴于此信息,我们可以进行以下观察:
Observation 1: A node x is the root of a non-BST if x ≤ max(x.left) or if x ≥ min(y.right)
这不是一个当且仅当条件 - 它只是一个 "if" - 但它是一个有用的观察结果。这样做的原因是,如果 x ≤ max(x.left),则 x 的左子树中有一个节点不小于 x,这意味着以 x 为根的树不是 BST,如果 x > min(x.right),则x的右子树中有一个节点不大于x,说明以x为根的树不是BST。
现在,x < min(x.right) 和 x > max(x.left) 的任何节点不一定是 BST 的根。考虑这棵树,例如:
4
/ \
1 6
/ \
2 5
这里,根节点比它的左子树的所有东西都大,比它的右子树的所有东西都小,但是整棵树本身并不是二叉搜索树。这是因为以 1 和 6 为根的树不是 BST。这导致了一个有用的观察:
Observation 2: If x > max(x.left) and x < min(x.right), then x is a BST if and only if x.left and x.right are BSTs.
此结果证明的快速草图:如果 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 根的每个节点。思路是从叶子向上遍历树中的节点,检查每个节点的值是否大于其左子树的max且小于其右子树的min,然后检查其左右子树是否为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 的最深节点。我将把它留作 reader 的众所周知的练习。 :-)
希望对您有所帮助!
我正在努力解决以下问题:
编写函数,对于给定的二叉树 returns 当树是 BST 时,最小高度的根不是 BST 或 NIL。
我知道如何检查树是否是 BST 但不知道如何重写它。 如果有伪代码算法,我将不胜感激。
我不想直接跳到此处适用的算法,而是给出一系列观察结果,最终得出一个非常好的算法来解决这个问题。
首先,假设对于树中的每个节点,您知道以该节点为根的子树中的最大值和最小值。 (我们将它们表示为 min(x) 和 max(x),其中 x 是树中的一个节点)。鉴于此信息,我们可以进行以下观察:
Observation 1: A node x is the root of a non-BST if x ≤ max(x.left) or if x ≥ min(y.right)
这不是一个当且仅当条件 - 它只是一个 "if" - 但它是一个有用的观察结果。这样做的原因是,如果 x ≤ max(x.left),则 x 的左子树中有一个节点不小于 x,这意味着以 x 为根的树不是 BST,如果 x > min(x.right),则x的右子树中有一个节点不大于x,说明以x为根的树不是BST。
现在,x < min(x.right) 和 x > max(x.left) 的任何节点不一定是 BST 的根。考虑这棵树,例如:
4
/ \
1 6
/ \
2 5
这里,根节点比它的左子树的所有东西都大,比它的右子树的所有东西都小,但是整棵树本身并不是二叉搜索树。这是因为以 1 和 6 为根的树不是 BST。这导致了一个有用的观察:
Observation 2: If x > max(x.left) and x < min(x.right), then x is a BST if and only if x.left and x.right are BSTs.
此结果证明的快速草图:如果 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 根的每个节点。思路是从叶子向上遍历树中的节点,检查每个节点的值是否大于其左子树的max且小于其右子树的min,然后检查其左右子树是否为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 的最深节点。我将把它留作 reader 的众所周知的练习。 :-)
希望对您有所帮助!