对于给定的二叉树,找到最大的子树,它也是二叉树吗?

例子:

输入:

                   10
               /         \
             50           150
            /  \         /   \
          25    75     200    20
         / \   / \    /  \    / \
        15 35 65 30  120 135 155 250

输出:
                   50
                  /   \
                 25   75
                / \   /
               15 35  65

最佳答案

该答案先前包含基于链接/剪切树的O(n log n)算法。这是一个更简单的 O(n)解决方案。

核心是一个程序,它接受一个节点,以其左子节点为根的唯一最大BSST,以其右子节点为根的唯一最大BSST以及指向这些BSST的最左侧和最右侧元素的指针。它破坏了其输入(避免使用持久数据结构),并构造了以给定节点为根的唯一最大BSST及其最小和最大元素。所有BSST节点均带有后代数目。与以前一样,从后遍历中反复调用此过程。要恢复子树,请记住最大的BSST的根。重建它只需要一个简单的遍历。

我将只处理左侧的BSST;右边是对称的。如果左BSST的根大于新的根,则将删除整个子树,并且新的根现在位于最左端。否则,旧的最左节点仍然是最左节点。从左BSST的最右节点开始向上移动,找到小于或等于根的第一个节点。它的合适的 child 必须被移走;现在请注意,由于具有BST属性,因此不需要其他节点!继续到左BSST的根,更新计数以反射(reflect)删除。

之所以是O(n),是因为尽管有循环,但原始树中的每个边缘实际上仅被遍历了一次。

编辑:总的来说,遍历的路径是BST中的最大直线路径,左脊椎和右脊椎除外。例如,在输入上

              H
             / \
            /   \
           /     \
          /       \
         /         \
        /           \
       /             \
      D               L
     / \             / \
    /   \           /   \
   /     \         /     \
  B       F       J       N
 / \     / \     / \     / \
A   C   E   G   I   K   M   O

这是遍历每个边的递归调用:
              H
             / \
            /   \
           /     \
          /       \
         /         \
        /           \
       /             \
      D               L
     / h             h \
    /   h           h   \
   /     h         h     \
  B       F       J       N
 / d     d h     h l     l \
A   C   E   G   I   K   M   O

09-25 21:20